Fixes for process exit before doing checks for syscalls etc.
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
index 909fbf2..8a79583 100644
--- a/sysdeps/linux-gnu/events.c
+++ b/sysdeps/linux-gnu/events.c
@@ -165,10 +165,51 @@
 		}
 	}
 
+	/* The process should be stopped after the waitpid call.  But
+	 * when the whole thread group is terminated, we see
+	 * individual tasks spontaneously transitioning from 't' to
+	 * 'R' and 'Z'.  Calls to ptrace fail and /proc/pid/status may
+	 * not even be available anymore, so we can't check in
+	 * advance.  So we just drop the error checking around ptrace
+	 * calls.  We check for termination ex post when it fails,
+	 * suppress the event, and let the event loop collect the
+	 * termination in the next iteration.  */
+#define CHECK_PROCESS_TERMINATED					\
+	do {								\
+		int errno_save = errno;					\
+		switch (process_stopped(pid))				\
+		case 0:							\
+		case -1: {						\
+			debug(DEBUG_EVENT,				\
+			      "process not stopped, is it terminating?"); \
+			event.type = EVENT_NONE;			\
+			continue_process(event.proc->pid);		\
+			return &event;					\
+		}							\
+		errno = errno_save;					\
+	} while (0)
+
 	event.proc->instruction_pointer = (void *)(uintptr_t)-1;
 
+	/* Check for task termination now, before we have a need to
+	 * call CHECK_PROCESS_TERMINATED later.  That would suppress
+	 * the event that we are processing.  */
+	if (WIFSIGNALED(status)) {
+		event.type = EVENT_EXIT_SIGNAL;
+		event.e_un.signum = WTERMSIG(status);
+		debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
+		return &event;
+	}
+	if (WIFEXITED(status)) {
+		event.type = EVENT_EXIT;
+		event.e_un.ret_val = WEXITSTATUS(status);
+		debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
+		return &event;
+	}
+
 	event.proc->instruction_pointer = get_instruction_pointer(event.proc);
 	if (event.proc->instruction_pointer == (void *)(uintptr_t)-1) {
+		CHECK_PROCESS_TERMINATED;
 		if (errno != 0)
 			perror("get_instruction_pointer");
 	}
@@ -195,10 +236,9 @@
 			debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
 			return &event;
 		case -1:
-			event.type = EVENT_NONE;
-			continue_process(event.proc->pid);
-			debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
-			return &event;
+			CHECK_PROCESS_TERMINATED;
+			if (errno != 0)
+				perror("syscall_p");
 	}
 	if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
 		unsigned long data;
@@ -213,18 +253,6 @@
 		debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
 		return &event;
 	}
-	if (WIFEXITED(status)) {
-		event.type = EVENT_EXIT;
-		event.e_un.ret_val = WEXITSTATUS(status);
-		debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
-		return &event;
-	}
-	if (WIFSIGNALED(status)) {
-		event.type = EVENT_EXIT_SIGNAL;
-		event.e_un.signum = WTERMSIG(status);
-		debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
-		return &event;
-	}
 	if (!WIFSTOPPED(status)) {
 		/* should never happen */
 		event.type = EVENT_NONE;