yoshi@cs.washingto.edu writes:>I'm doing a survey on methods programmers utilize in dealing with bugs>caused due to non-local dependencies.

The method I know best is to implement an internal trace -- a circular
array of entries describing *every* global-state transition that might
matter. Put wrappers on allocation, locks, message passing, cache loads/
spills, queues, async dispatch/exit... Make the in-core trace entries
semi-usable in a dump by putting an eyecatcher at the front of each and
making the union size match the number of bytes your dump formatter prints
on a line or two. Then in the wrappers fill out a local trace entry and
pass its address to the tracer, which copies it to the next entry in the
circular array. Leave the traces in and turned on, always. When your
program detects something seriously wrong, just dump core. If (since)
you're juggling multiple units of work, don't forget to have some way of
determining the guilty party for each entry, and trace the initiation and
completion of each. Force a few dumps in perfectly good situations so you
know what normal behavior looks like, and try to reconstruct exactly what
happened from the trace. If you can't, or feel you got lucky, figure out
what's missing and trace that.
--