Fixes for bug 1081, bug 1104 (fork test bugs)
authorDaniel McNulty <mcnulty@cs.wisc.edu>
Tue, 16 Nov 2010 21:42:27 +0000 (15:42 -0600)
committerDaniel McNulty <mcnulty@cs.wisc.edu>
Tue, 16 Nov 2010 21:42:27 +0000 (15:42 -0600)
commitca2f82cf37b2314e7572c4b8739ff6dede61f45d
tree76133656e9cabcb7dcad1ceafa734f3944b48061
parent346132a0d0ae08bde9f16b3a95cda697d1cb30af
Fixes for bug 1081, bug 1104 (fork test bugs)

Both of these bugs were caused by a combination of OS bugs and our fork tests
using mutatees where the parent can exit before the child and both the child
and parent are short lived. Both of the OS bugs were reproduced using test
programs separate from Dyninst, so I am confident we are indeed observing
kernel bugs.

This commit, in addition to fixes for these bugs, removes the extra continues
in our test_fork_* tests that were added to avoid leaving around a bunch of
stopped processes when the nightlies ran.

Bug 1081:

We were seeing the fork tests leave around stopped mutatees on AIX. This bug
was being triggered by our soft breakpoint mechanism in the RT library that has
a process send itself a SIGSTOP. The following chain of events triggers the
bug:

1) The parent forks a child
2) The child sends itself a SIGSTOP
3) Dyninst continues both the parent and child
4) The parent exits before the child
5) The child exits almost immediately after being forked
6) Dyninst sees the pre-exit stop of the child and continues it
7) After continue the child is delivered a SIGSTOP by the OS

We originally used the soft breakpoint mechanism because we could not rely on
AIX to attach to and stop a child after fork. This was a bug on version 5.2 of
AIX. Since we have decided to no longer support AIX 5.2, we can rely on the OS
to automatically mark forked processes as being traced by Dyninst. Ideally, we
would want to stop both the parent and child at the exit of fork to initiate
some updates in the RT library using the OS provided mechanism for this. Due to
some probably more OS bugs, this cannot be done.

AIX 5.3 still exhibits some odd behavior where LWPs cannot be modified
on syscall entry/exit. An existing workaround for this is to set a trap at
the exit of the system call. This is done by reading registers and walking
the stack (if necessary). However, for the child at the exit of fork, the
values read from the registers are unreliable.

Working around all these bugs, the solution becomes to use a SIGTRAP instead of
a SIGSTOP in our soft breakpoint mechansim.

Bug 1104:

For test4_2, we were seeing a race where the exit callback of the child was not
being delivered, causing the test to fail. This bug in Dyninst was being
triggered by another kernel bug where if the parent exited before the child
entered userland for the first time, the child process would never execute.

In this scenario, Dyninst would observe that the child process disappeared and
generate an approriate event. On UNIX platforms, we however don't deliver
callbacks on a normal process exit; we deliver them at the entrance to the exit
system call when the process' address space is still around.  In this case, the
child doesn't hit our pre-exit instrumentation and we therefore don't deliver
the callback.

The fix is to check whether a callback has been attempted to be delivered when
we receive the process exit event and deliver the callback if it hasn't been
delivered yet. Additionally, the type of callback delivered is the same as if
the process had exited due to a signal because the process' address space is
not around anymore. When the kernel bug occurs, this would still cause the
test to fail so I have modified the mutatee's parent to wait for the child.
12 files changed:
dyninstAPI/src/signalhandler.C
dyninstAPI_RT/src/RTaix.c
testsuite/src/dyninst/test4_2_mutatee.c
testsuite/src/dyninst/test_fork_10.C
testsuite/src/dyninst/test_fork_11.C
testsuite/src/dyninst/test_fork_12.C
testsuite/src/dyninst/test_fork_13.C
testsuite/src/dyninst/test_fork_5.C
testsuite/src/dyninst/test_fork_6.C
testsuite/src/dyninst/test_fork_7.C
testsuite/src/dyninst/test_fork_8.C
testsuite/src/dyninst/test_fork_9.C