* process.c: Add a comment. No code changes.
* strace.c (collect_stopped_tcbs): Stop reversing list of stopped
tcp's. I'm not totally convinced it is crucial, but this is surely
fits the concept of "least surprise".
Do not collect TCB_SUSPENDED tcp's (this is closer to how
it was before).
(handle_stopped_tcbs): Remove the code to reject TCB_SUSPENDED tcp's,
it's done earlier now. In an unobvious way, this was causing
SIGSTOPs from freshly attached children to be misinterpreted.
diff --git a/ChangeLog b/ChangeLog
index 5bfd7db..0102ce8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-01-17  Denys Vlasenko  <dvlasenk@redhat.com>
+
+	* process.c: Add a comment. No code changes.
+	* strace.c (collect_stopped_tcbs): Stop reversing list of stopped
+	tcp's. I'm not totally convinced it is crucial, but this is surely
+	fits the concept of "least surprise".
+	Do not collect TCB_SUSPENDED tcp's (this is closer to how
+	it was before).
+	(handle_stopped_tcbs): Remove the code to reject TCB_SUSPENDED tcp's,
+	it's done earlier now. In an unobvious way, this was causing
+	SIGSTOPs from freshly attached children to be misinterpreted.
+
 2009-01-14  Denys Vlasenko  <dvlasenk@redhat.com>
 
 	* linux/bfin/syscallent.h: sys_futex has 6 parameters, not 5.
diff --git a/process.c b/process.c
index 03cd251..7107361 100644
--- a/process.c
+++ b/process.c
@@ -963,6 +963,9 @@
 				clearbpt(tcpchild);
 
 			tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
+			/* TCB_SUSPENDED tasks are not collected by waitpid
+			 * loop, and left stopped. Restart it:
+			 */
 			if (ptrace_restart(PTRACE_SYSCALL, tcpchild, 0) < 0)
 				return -1;
 
diff --git a/strace.c b/strace.c
index 57945db..80d468a 100644
--- a/strace.c
+++ b/strace.c
@@ -2279,7 +2279,8 @@
 	struct rusage ru;
 	struct rusage* ru_ptr = cflag ? &ru : NULL;
 	int wnohang = 0;
-	struct tcb *found_tcps = NULL;
+	struct tcb *found_tcps;
+	struct tcb **nextp = &found_tcps;
 #ifdef __WALL
 	int wait4_options = __WALL;
 #endif
@@ -2401,30 +2402,6 @@
 			tcp->stime = ru.ru_stime;
 #endif
 		}
-		tcp->wait_status = status;
-#ifdef LINUX
-		tcp->next_need_service = found_tcps;
-		found_tcps = tcp;
-		wnohang = WNOHANG;
-#endif
-#ifdef SUNOS4
-		/* Probably need to replace wait with waitpid
-		 * and loop on Sun too, but I can't test it. Volunteers?
-		 */
-		break;
-#endif
-	} /* while (1) - collecting all stopped/exited tracees */
-
-	return tcp;
-}
-
-static int
-handle_stopped_tcbs(struct tcb *tcp)
-{
-	for (; tcp; tcp = tcp->next_need_service) {
-		int pid;
-		int status;
-
 		if (tcp->flags & TCB_SUSPENDED) {
 			/*
 			 * Apparently, doing any ptrace() call on a stopped
@@ -2437,6 +2414,37 @@
 			continue;
 		}
 
+		tcp->wait_status = status;
+#ifdef LINUX
+		/* It is important to not invert the order of tasks
+		 * to process. For one, alloc_tcb() above picks newly forked
+		 * threads in some order, processing of them and their parent
+		 * should be in the same order, otherwise bad things happen
+		 * (misinterpreted SIGSTOPs and such).
+		 */
+		*nextp = tcp;
+		nextp = &tcp->next_need_service;
+		wnohang = WNOHANG;
+#endif
+#ifdef SUNOS4
+		/* Probably need to replace wait with waitpid
+		 * and loop on Sun too, but I can't test it. Volunteers?
+		 */
+		break;
+#endif
+	}
+
+	*nextp = NULL;
+	return found_tcps;
+}
+
+static int
+handle_stopped_tcbs(struct tcb *tcp)
+{
+	for (; tcp; tcp = tcp->next_need_service) {
+		int pid;
+		int status;
+
 		outf = tcp->outf;
 		status = tcp->wait_status;
 		pid = tcp->pid;