Logging

libgreat now logs what it's up to internally. Here's an example:

clarion% LD_PRELOAD=libgreat_c99.so uname
Thu Mar 13 22:19:46 2008 libgreat_c99 GREAT_RANDOM_SEED INFO: Defaulting to 5489
Thu Mar 13 22:19:46 2008 libgreat_c99 GREAT_SUBSETS INFO: Registered subset: /./
Thu Mar 13 22:19:46 2008 libgreat_c99 stdio:memory:malloc DEFAULT
Thu Mar 13 22:19:46 2008 libgreat_c99 stdio:memory:free DEFAULT
Thu Mar 13 22:19:46 2008 libgreat_c99 stdio:memory:malloc [C99 7.20.3.3 P3] IB: Returning NULL
zsh: segmentation fault  LD_PRELOAD=libgreat_c99.so uname
clarion*

Here we can see a few preliminary bits and pieces being initialised (such as seeding the PRNG for deciding when to cause failures to occur).

Then we see malloc() being called, and (randomly) defaulting to call the underlying system's malloc(). Likewise free() defaults, and then malloc() is called again. This time, malloc() decided to (randomly) return NULL. As for all interceptions, this behaviour is justified in the log message, quoting the section of the appropriate standard which permits that behaviour.

Unfortunately, NetBSD's uname doesn't seem too happy with that, and promptly segfaults.

The file to which logs are sent defaults to standard output. This may be set explicitly by way of $GREAT_LOG:

clarion% LD_PRELOAD=libgreat_c99.so GREAT_LOG=/dev/null cat
zsh: segmentation fault  LD_PRELOAD=libgreat_c99.so GREAT_LOG=/dev/null cat
clarion*

You can see the guts behind logging at shared/log.h.