[patch] test/leaderkill fix

Jan Kratochvil jan.kratochvil at redhat.com
Fri Aug 3 10:22:56 UTC 2007


On Fri, 03 Aug 2007 12:06:13 +0200, Roland McGrath wrote:
> I put this in.  I confess I didn't think too deeply about it, but what
> you've said makes sense.

I had before the attached patch which detached all the tasks first and so it
does not need the other two fixes there.  It also fixed the testcase run.

Still I believe those two fixes were right and the accepted patch is more
foolproof+simpler this way.


Thanks,
Jan
-------------- next part --------------
2007-08-01  Jan Kratochvil  <jan.kratochvil at redhat.com>

	* strace.c (handle_group_exit): Fix hang while tracing _exit(2) of
	a child with sibling(s) for TCB_ATTACHED tasks.

	* test/leaderkill2.c (start): Renamed to ...
	(start0): ... here.
	(start1): New function.
	(main): Created a new spare thread.

--- strace.c	11 Jul 2007 08:35:11 -0000	1.81
+++ strace.c	1 Aug 2007 22:03:00 -0000
@@ -2115,22 +2115,57 @@ handle_group_exit(struct tcb *tcp, int s
 		/* Mark that we are taking the process down.  */
 		tcp->flags |= TCB_EXITING | TCB_GROUP_EXITING;
 		if (tcp->flags & TCB_ATTACHED) {
-			detach(tcp, sig);
-		  	if (leader != NULL && leader != tcp) {
-				if ((leader->flags & TCB_ATTACHED) &&
-				    !(leader->flags & TCB_EXITING)) {
-					/* We need to detach the leader so
-					   that the process death will be
-					   reported to its real parent.  */
+			/* TCP->PID becomes free()d later.  */
+			int pid = tcp->pid;
+			int tcbi;
+			struct tcb *tciterp;
+			int leader_met = 0;
+
+			/* Leader must be detached as the very last task.
+			   Any of its undetached task-group children would hang
+			   us on waitpid() during the leader's detachment.
+			   Testcase: test/leaderkill2.c  */
+			for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
+				tciterp = tcbtab[tcbi];
+				if (!(tciterp->flags & TCB_INUSE))
+					continue;
+				if (!(tciterp->flags & TCB_ATTACHED))
+					continue;
+				/* Just a leftover stub TCB structure?  */
+				if ((tciterp->flags & TCB_EXITING)
+				    && tciterp != tcp)
+					continue;
+				/* Unrelated task?  We are interested in any
+				   task in a clone-relationship with TCP.
+				   Detachee itself or its leader?  */
+				if (!(tciterp == tcp || tciterp == leader
+				      || ((tciterp->flags & TCB_CLONE_THREAD)
+				  /* Child of our detachee-being-the-leader?  */
+					  && (tciterp->parent == tcp
+					    /* Sibling of our common leader?  */
+					      || tciterp->parent == leader))))
+					continue;
+				if (tciterp == leader)
+					leader_met = 1;
+				else {
 					if (debug)
 						fprintf(stderr,
-							" [%d exit %d detaches %d]\n",
-							tcp->pid, sig, leader->pid);
-					detach(leader, sig);
+							" [%d exit %d"
+							" detaches %d]\n",
+							pid, sig, tciterp->pid);
+					detach(tciterp, sig);
 				}
-				else
-					leader->flags |= TCB_GROUP_EXITING;
 			}
+			if (leader_met) {
+				if (debug)
+					fprintf(stderr,
+						" [%d exit %d"
+						" detaches leader %d]\n",
+						pid, sig, leader->pid);
+				detach(leader, sig);
+			}
+			else if (leader != NULL)
+				leader->flags |= TCB_GROUP_EXITING;
 		}
 		else if (ptrace(PTRACE_CONT, tcp->pid, (char *) 1, sig) < 0) {
 			perror("strace: ptrace(PTRACE_CONT, ...)");
--- test/leaderkill.c	5 Jul 2007 18:43:18 -0000	1.1
+++ test/leaderkill.c	1 Aug 2007 22:03:08 -0000
@@ -13,15 +13,23 @@
 #include <stdio.h>
 #include <sys/wait.h>
 
-static void *start (void *arg)
+static void *start0 (void *arg)
 {
   sleep (1);
 
   exit (42);
 }
 
+static void *start1 (void *arg)
+{
+  pause ();
+  /* NOTREACHED */
+  assert (0);
+}
+
 int main (void)
 {
+  pthread_t thread0;
   pthread_t thread1;
   int i;
   pid_t child, got_pid;
@@ -35,16 +43,13 @@ int main (void)
       case -1:
 	abort ();
       case 0:
-	i = pthread_create (&thread1, NULL, start, NULL);
+	i = pthread_create (&thread0, NULL, start0, NULL);
+	assert (i == 0);
+	i = pthread_create (&thread1, NULL, start1, NULL);
 	assert (i == 0);
-/* Two possible testcases; the second one passed even in the older versions.  */
-#if 1
 	pause ();
-#else
-	pthread_exit (NULL);
-#endif
 	/* NOTREACHED */
-	abort ();
+	assert (0);
 	break;
       default:
 	got_pid = waitpid (child, &status, 0);


More information about the Strace-devel mailing list