Source: MontaVista Software, Inc.
Type: Defect Fix
Disposition: merge to rpm.org
Description:
    Cygwin appears to have issues w/ sending signals to blocked processes.
    This patch reverts the normal rpm asyncronous reaper processing with
    the "waitpid" approach.

    If any other systems experience deadlocked scriptlets, this might be
    a first approach at a workaround.

Index: rpm-4.3.3/lib/psm.c
===================================================================
--- rpm-4.3.3.orig/lib/psm.c
+++ rpm-4.3.3/lib/psm.c
@@ -536,7 +536,11 @@
     if (progArgv == NULL && script == NULL)
 	return rc;
 
+#if !defined(__CYGWIN__)
     psm->sq.reaper = 1;
+#else
+    psm->sq.reaper = 0;
+#endif
 
     /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
     xx = headerNVR(h, &n, &v, &r);
@@ -697,6 +701,9 @@
 	int flag;
 	int fdno;
 
+if (_psm_debug)
+fprintf(stderr, "--> psm runScript %s\n", argv[0]);
+
 	pipes[0] = pipes[1] = 0;
 	/* make stdin inaccessible */
 	xx = pipe(pipes);
Index: rpm-4.3.3/rpmio/rpmsq.c
===================================================================
--- rpm-4.3.3.orig/rpmio/rpmsq.c
+++ rpm-4.3.3/rpmio/rpmsq.c
@@ -392,7 +392,6 @@
 {
     pid_t pid;
     int xx;
-    int nothreads = 0;   /* XXX: Shouldn't this be a global? */
 
     if (sq->reaper) {
 	xx = rpmsqInsert(sq, NULL);
@@ -401,9 +400,15 @@
 fprintf(stderr, "    Enable(%p): %p\n", ME(), sq);
 #endif
 	xx = rpmsqEnable(SIGCHLD, NULL);
-    }
 
-    xx = pipe(sq->pipes);
+        xx = pipe(sq->pipes);
+    } else {
+	/* Reset the contents of sq! */
+	/* rpmsqInsert normally does this */
+	sq->child = 0;
+	sq->reaped = 0;
+	sq->status = 0;
+    }
 
     xx = sighold(SIGCHLD);
 
@@ -413,7 +418,7 @@
      * the child to exit, we get sigchild and the sig handler to send 
      * the condition signal before we are waiting on the condition.
      */
-    if (!nothreads) {
+    if (sq->reaper) {
 	if(pthread_mutex_lock(&sq->mutex)) {
 	    /* Yack we did not get the lock, lets just give up */
 /*@-bounds@*/
@@ -428,20 +433,24 @@
     pid = fork();
     if (pid < (pid_t) 0) {		/* fork failed.  */
 /*@-bounds@*/
-	xx = close(sq->pipes[0]);
-	xx = close(sq->pipes[1]);
-	sq->pipes[0] = sq->pipes[1] = -1;
+	if (sq->reaper) {
+	  xx = close(sq->pipes[0]);
+	  xx = close(sq->pipes[1]);
+	  sq->pipes[0] = sq->pipes[1] = -1;
+	}
 /*@=bounds@*/
 	goto out;
     } else if (pid == (pid_t) 0) {	/* Child. */
 	int yy;
 
+	if (sq->reaper) {
 	/* Block to permit parent time to wait. */
 /*@-bounds@*/
-	xx = close(sq->pipes[1]);
-	xx = read(sq->pipes[0], &yy, sizeof(yy));
-	xx = close(sq->pipes[0]);
-	sq->pipes[0] = sq->pipes[1] = -1;
+	  xx = close(sq->pipes[1]);
+	  xx = read(sq->pipes[0], &yy, sizeof(yy));
+	  xx = close(sq->pipes[0]);
+	  sq->pipes[0] = sq->pipes[1] = -1;
+	}
 /*@=bounds@*/
 
 #ifdef _RPMSQ_DEBUG
@@ -475,7 +484,6 @@
 	/*@globals fileSystem, internalState @*/
 	/*@modifies sq, fileSystem, internalState @*/
 {
-    int nothreads = 0;
     int ret = 0;
     int xx;
 
@@ -497,10 +505,7 @@
     /* Wait for handler to receive SIGCHLD. */
     /*@-infloops@*/
     while (ret == 0 && sq->reaped != sq->child) {
-	if (nothreads)
-	    /* Note that sigpause re-enables SIGCHLD. */
-	    ret = sigpause(SIGCHLD);
-	else {
+	if (sq->reaper) {
 	    xx = sigrelse(SIGCHLD);
 	    
 	    /* 
@@ -510,7 +515,9 @@
 	     */
 	    ret = pthread_mutex_lock(&sq->mutex);
 	    xx = sighold(SIGCHLD);
-	}
+	} else
+	    /* Note that sigpause re-enables SIGCHLD. */
+	    ret = sigpause(SIGCHLD);
     }
     /*@=infloops@*/
 
@@ -553,6 +560,7 @@
 	do {
 	    reaped = waitpid(sq->child, &status, 0);
 	} while (reaped >= 0 && reaped != sq->child);
+assert(!(reaped == -1 && errno == ECHILD));
 	sq->reaped = reaped;
 	sq->status = status;
 #ifdef _RPMSQ_DEBUG
