diff -urp ltrace-0.5/ltrace.h ltrace-0.5-pm/ltrace.h --- ltrace-0.5/ltrace.h 2009-03-03 02:07:44.000000000 +0100 +++ ltrace-0.5-pm/ltrace.h 2009-03-03 02:07:19.000000000 +0100 @@ -107,6 +107,9 @@ struct process { int mask_32bit; /* 1 if 64-bit ltrace is tracing 32-bit process. */ unsigned int personality; int tracesysgood; /* signal indicating a PTRACE_SYSCALL trap */ + int early; /* for consistency checks, this is true for + * children whose TRAP was delivered before + * the fork message of the parent. */ int callstack_depth; struct callstack_element callstack[MAX_CALLDEPTH]; @@ -173,7 +176,7 @@ extern void reinitialize_breakpoints(str extern struct process *open_program(char *filename, pid_t pid); extern void open_pid(pid_t pid, int verbose); -extern void open_forked_pid(pid_t pid); +extern void open_forked_pid(pid_t pid, int early); extern void show_summary(void); /* Arch-dependent stuff: */ diff -urp ltrace-0.5/proc.c ltrace-0.5-pm/proc.c --- ltrace-0.5/proc.c 2009-03-03 02:07:44.000000000 +0100 +++ ltrace-0.5-pm/proc.c 2009-03-03 02:07:19.000000000 +0100 @@ -59,10 +59,11 @@ void open_pid(pid_t pid, int verbose) proc->pid = pid; } -void open_forked_pid(pid_t pid) +void open_forked_pid(pid_t pid, int early) { char *filename = pid2name(pid); struct process *proc = open_program(filename, 0); proc->pid = pid; proc->breakpoints_enabled = -1; + proc->early = early; } diff -urp ltrace-0.5/wait_for_something.c ltrace-0.5-pm/wait_for_something.c --- ltrace-0.5/wait_for_something.c 2009-03-03 02:07:44.000000000 +0100 +++ ltrace-0.5-pm/wait_for_something.c 2009-03-03 02:07:19.000000000 +0100 @@ -45,10 +45,24 @@ struct event *wait_for_something(void) perror("wait"); exit(1); } + event.proc = pid2proc(pid); if (!event.proc) { - fprintf(stderr, "signal from wrong pid %u ?!?\n", pid); - exit(1); + if(!opt_f) { + fprintf(stderr, "signal from wrong pid %u ?!?\n", pid); + exit(1); + } else { + /* Parent forked, but we got child's STOP + * signal first. */ + debug (1, "signal from forked child delivered ahead of time?"); + + event.thing = LT_EV_NONE; + event.e_un.signum = WSTOPSIG(status); + open_forked_pid(pid, 1); + event.proc = pid2proc(pid); + continue_after_signal(event.proc->pid, event.e_un.signum); + return &event; + } } get_arch_dep(event.proc); event.proc->instruction_pointer = NULL; @@ -104,7 +118,18 @@ struct event *wait_for_something(void) child_pid = (pid_t) get_child_pid(event.proc->pid); if (child_pid){ debug (3, "fork: get_child_pid gave us %d", child_pid); - open_forked_pid(child_pid); + + struct process *it = list_of_processes; + for (; it != NULL; it = it->next) + if (it->pid == child_pid) { + if (!it->early) + fprintf (stderr, + "Child %d re-delivered.\n", + child_pid); + break; + } + if (!it) + open_forked_pid(child_pid, 0); } enable_all_breakpoints(event.proc); continue_after_signal(event.proc->pid, event.e_un.signum);