teknoraver / rpms / rpm

Forked from rpms/rpm 4 months ago
Clone

Blame rpm-4.4.2-rpmsq-deadlock.patch

Paul Nasrat 2c77b0
--- rpm-4.4.2/rpmio/rpmsq.c.deadlock	2005-07-13 06:47:03.000000000 -0400
Paul Nasrat 2c77b0
+++ rpm-4.4.2/rpmio/rpmsq.c	2006-01-30 21:00:13.000000000 -0500
Paul Nasrat 2c77b0
@@ -218,7 +218,6 @@
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
 	    sq->id = ME();
Paul Nasrat 2c77b0
 	    ret = pthread_mutex_init(&sq->mutex, NULL);
Paul Nasrat 2c77b0
-	    ret = pthread_cond_init(&sq->cond, NULL);
Paul Nasrat 2c77b0
 	    insque(elem, (prev != NULL ? prev : rpmsqQueue));
Paul Nasrat 2c77b0
 	    ret = sigrelse(SIGCHLD);
Paul Nasrat 2c77b0
 	}
Paul Nasrat 2c77b0
@@ -240,8 +239,11 @@
Paul Nasrat 2c77b0
 	ret = sighold (SIGCHLD);
Paul Nasrat 2c77b0
 	if (ret == 0) {
Paul Nasrat 2c77b0
 	    remque(elem);
Paul Nasrat 2c77b0
-	    ret = pthread_cond_destroy(&sq->cond);
Paul Nasrat 2c77b0
-	    ret = pthread_mutex_destroy(&sq->mutex);
Paul Nasrat 2c77b0
+	   
Paul Nasrat 2c77b0
+	    /* Unlock the mutex and then destroy it */ 
Paul Nasrat 2c77b0
+	    if((ret = pthread_mutex_unlock(&sq->mutex)) == 0)
Paul Nasrat 2c77b0
+		ret = pthread_mutex_destroy(&sq->mutex);
Paul Nasrat 2c77b0
+
Paul Nasrat 2c77b0
 	    sq->id = NULL;
Paul Nasrat 2c77b0
 /*@-bounds@*/
Paul Nasrat 2c77b0
 	    if (sq->pipes[1])	ret = close(sq->pipes[1]);
Paul Nasrat 2c77b0
@@ -315,11 +317,20 @@
Paul Nasrat 2c77b0
 		     sq != NULL && sq != rpmsqQueue;
Paul Nasrat 2c77b0
 		     sq = sq->q_forw)
Paul Nasrat 2c77b0
 		{
Paul Nasrat 2c77b0
+		    int ret;
Paul Nasrat 2c77b0
+
Paul Nasrat 2c77b0
 		    if (sq->child != reaped)
Paul Nasrat 2c77b0
 			/*@innercontinue@*/ continue;
Paul Nasrat 2c77b0
 		    sq->reaped = reaped;
Paul Nasrat 2c77b0
 		    sq->status = status;
Paul Nasrat 2c77b0
-		    (void) pthread_cond_signal(&sq->cond);
Paul Nasrat 2c77b0
+
Paul Nasrat 2c77b0
+		    /* Unlock the mutex.  The waiter will then be able to 
Paul Nasrat 2c77b0
+		     * aquire the lock.  
Paul Nasrat 2c77b0
+		     *
Paul Nasrat 2c77b0
+		     * XXX: jbj, wtd, if this fails? 
Paul Nasrat 2c77b0
+		     */
Paul Nasrat 2c77b0
+		    ret = pthread_mutex_unlock(&sq->mutex); 
Paul Nasrat 2c77b0
+
Paul Nasrat 2c77b0
 		    /*@innerbreak@*/ break;
Paul Nasrat 2c77b0
 		}
Paul Nasrat 2c77b0
 	    }
Paul Nasrat 2c77b0
@@ -391,6 +402,7 @@
Paul Nasrat 2c77b0
 {
Paul Nasrat 2c77b0
     pid_t pid;
Paul Nasrat 2c77b0
     int xx;
Paul Nasrat 2c77b0
+    int nothreads = 0;   /* XXX: Shouldn't this be a global? */
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
     if (sq->reaper) {
Paul Nasrat 2c77b0
 	xx = rpmsqInsert(sq, NULL);
Paul Nasrat 2c77b0
@@ -405,6 +417,24 @@
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
     xx = sighold(SIGCHLD);
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
+    /* 
Paul Nasrat 2c77b0
+     * Initialize the cond var mutex.   We have to aquire the lock we 
Paul Nasrat 2c77b0
+     * use for the condition before we fork.  Otherwise it is possible for
Paul Nasrat 2c77b0
+     * the child to exit, we get sigchild and the sig handler to send 
Paul Nasrat 2c77b0
+     * the condition signal before we are waiting on the condition.
Paul Nasrat 2c77b0
+     */
Paul Nasrat 2c77b0
+    if (!nothreads) {
Paul Nasrat 2c77b0
+	if(pthread_mutex_lock(&sq->mutex)) {
Paul Nasrat 2c77b0
+	    /* Yack we did not get the lock, lets just give up */
Paul Nasrat 2c77b0
+/*@-bounds@*/
Paul Nasrat 2c77b0
+	    xx = close(sq->pipes[0]);
Paul Nasrat 2c77b0
+	    xx = close(sq->pipes[1]);
Paul Nasrat 2c77b0
+	    sq->pipes[0] = sq->pipes[1] = -1;
Paul Nasrat 2c77b0
+/*@=bounds@*/
Paul Nasrat 2c77b0
+	    goto out;
Paul Nasrat 2c77b0
+	}
Paul Nasrat 2c77b0
+    }
Paul Nasrat 2c77b0
+
Paul Nasrat 2c77b0
     pid = fork();
Paul Nasrat 2c77b0
     if (pid < (pid_t) 0) {		/* fork failed.  */
Paul Nasrat 2c77b0
 /*@-bounds@*/
Paul Nasrat 2c77b0
@@ -462,10 +492,6 @@
Paul Nasrat 2c77b0
     /* Protect sq->reaped from handler changes. */
Paul Nasrat 2c77b0
     ret = sighold(SIGCHLD);
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
-    /* Initialize the cond var mutex. */
Paul Nasrat 2c77b0
-    if (!nothreads)
Paul Nasrat 2c77b0
-	ret = pthread_mutex_lock(&sq->mutex);
Paul Nasrat 2c77b0
-
Paul Nasrat 2c77b0
     /* Start the child, linux often runs child before parent. */
Paul Nasrat 2c77b0
 /*@-bounds@*/
Paul Nasrat 2c77b0
     if (sq->pipes[0] >= 0)
Paul Nasrat 2c77b0
@@ -486,7 +512,13 @@
Paul Nasrat 2c77b0
 	    ret = sigpause(SIGCHLD);
Paul Nasrat 2c77b0
 	else {
Paul Nasrat 2c77b0
 	    xx = sigrelse(SIGCHLD);
Paul Nasrat 2c77b0
-	    ret = pthread_cond_wait(&sq->cond, &sq->mutex);
Paul Nasrat 2c77b0
+	    
Paul Nasrat 2c77b0
+	    /* 
Paul Nasrat 2c77b0
+	     * We start before the fork with this mutex locked;
Paul Nasrat 2c77b0
+	     * The only one that unlocks this the signal handler.
Paul Nasrat 2c77b0
+	     * So if we get the lock the child has been reaped.
Paul Nasrat 2c77b0
+	     */
Paul Nasrat 2c77b0
+	    ret = pthread_mutex_lock(&sq->mutex);
Paul Nasrat 2c77b0
 	    xx = sighold(SIGCHLD);
Paul Nasrat 2c77b0
 	}
Paul Nasrat 2c77b0
     }
Paul Nasrat 2c77b0
@@ -495,9 +527,6 @@
Paul Nasrat 2c77b0
     /* Accumulate stopwatch time spent waiting, potential performance gain. */
Paul Nasrat 2c77b0
     sq->ms_scriptlets += rpmswExit(&sq->op, -1)/1000;
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
-    /* Tear down cond var mutex, our child has been reaped. */
Paul Nasrat 2c77b0
-    if (!nothreads)
Paul Nasrat 2c77b0
-	xx = pthread_mutex_unlock(&sq->mutex);
Paul Nasrat 2c77b0
     xx = sigrelse(SIGCHLD);
Paul Nasrat 2c77b0
 
Paul Nasrat 2c77b0
 #ifdef _RPMSQ_DEBUG