Subject: Re: libpthread/sem.c rev 1.8 breaks python
To: Quentin Garnier <cube@cubidou.net>
From: Chuck Silvers <chuq@chuq.com>
List: current-users
Date: 10/18/2005 06:54:12
--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Tue, Oct 18, 2005 at 11:38:58AM +0200, Quentin Garnier wrote:
> On Tue, Oct 18, 2005 at 11:32:46AM +0200, Juan RP wrote:
> > On Tue, 18 Oct 2005 10:55:26 +0200
> > Juan RP <juan@xtrarom.org> wrote:
> > 
> > > 
> > > Hi, 
> > > 
> > > Looks like after your change to libpthread/sem.c, python2[34]
> > > core dumps when starting xend (required for NetBSD/Xen).
> > > 
> > > backtraces for python23 and python24 from pkgsrc:
> > > 
> > > http://www.xtrarom.org/pthread_python2.3.txt
> > > http://www.xtrarom.org/pthread_python2.4.txt
> > > 
> > > Reverting to 1.7 seems to work again.
> > 
> > kdump (ktrace -i) output available at:
> > 
> > ftp://ftp.netbsd.org/pub/NetBSD/misc/xtraeme/python_kdump.out.bz2
> 
> What happens in process 1481 (the first one to abort()) is a failed
> pthread initialisation.  It really looks like rrtimer_created is set
> to 1 in pthread__setrrtimer when the program gets there from
> pthread__sa_start:  the timer is not created, and timer_settime(2)
> returns EINVAL because the referenced timer doesn't exist.
> 
> Could it be tied to the fact that process 2293 performs a pthread
> initialisation, and then forks child 1481?

yea, that's the problem.  the process is still single-threaded,
but my fix for sem_wait() in single-threaded processes starts
the library anyway, which then causes problems in the child after
it forks.  looks like starting the library isn't such a good idea.

here's a different set of fixes for the various problems I was trying
to fix with those extra calls to pthread__start().  does xend work again
with these changes?

-Chuck

--FCuugMFkClbJLl1L
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="z.nostart"

Index: pthread.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread.c,v
retrieving revision 1.44
diff -u -p -r1.44 pthread.c
--- pthread.c	16 Oct 2005 00:37:52 -0000	1.44
+++ pthread.c	18 Oct 2005 13:43:15 -0000
@@ -237,7 +237,7 @@ pthread__child_callback(void)
 	pthread__started = 0;
 }
 
-void
+static void
 pthread__start(void)
 {
 	pthread_t self, idle;
Index: pthread_int.h
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_int.h,v
retrieving revision 1.32
diff -u -p -r1.32 pthread_int.h
--- pthread_int.h	16 Oct 2005 00:07:24 -0000	1.32
+++ pthread_int.h	18 Oct 2005 13:43:16 -0000
@@ -274,7 +274,6 @@ pthread_t pthread__next(pthread_t self);
 
 int	pthread__stackalloc(pthread_t *t);
 void	pthread__initmain(pthread_t *t);
-void	pthread__start(void);
 
 void	pthread__sa_start(void);
 void	pthread__sa_recycle(pthread_t old, pthread_t new);
Index: pthread_mutex.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_mutex.c,v
retrieving revision 1.20
diff -u -p -r1.20 pthread_mutex.c
--- pthread_mutex.c	16 Oct 2005 00:07:24 -0000	1.20
+++ pthread_mutex.c	18 Oct 2005 13:43:16 -0000
@@ -189,16 +189,10 @@ static int
 pthread_mutex_lock_slow(pthread_mutex_t *mutex)
 {
 	pthread_t self;
-	extern int pthread__started;
 
 	pthread__error(EINVAL, "Invalid mutex",
 	    mutex->ptm_magic == _PT_MUTEX_MAGIC);
 
-	if (pthread__started == 0) {
-		pthread__start();
-		pthread__started = 1;
-	}
-
 	self = pthread__self();
 
 	PTHREADD_ADD(PTHREADD_MUTEX_LOCK_SLOW);
@@ -245,6 +239,19 @@ pthread_mutex_lock_slow(pthread_mutex_t 
 						return EAGAIN;
 					mp->recursecount++;
 					return 0;
+
+				case PTHREAD_MUTEX_NORMAL:
+					/*
+					 * The spec says we must deadlock, so...
+					 */
+					for (;;) {
+						sigset_t ss;
+
+						(void) sigprocmask(SIG_SETMASK,
+								   NULL, &ss);
+						sigsuspend(&ss);
+					}
+					/*NOTREACHED*/
 				}
 			}
 
Index: pthread_rwlock.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_rwlock.c,v
retrieving revision 1.12
diff -u -p -r1.12 pthread_rwlock.c
--- pthread_rwlock.c	16 Oct 2005 00:07:24 -0000	1.12
+++ pthread_rwlock.c	18 Oct 2005 13:43:16 -0000
@@ -169,6 +169,8 @@ int
 pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
 {
 	pthread_t self;
+	extern int pthread__started;
+
 #ifdef ERRORCHECK
 	if ((rwlock == NULL) || (rwlock->ptr_magic != _PT_RWLOCK_MAGIC))
 		return EINVAL;
@@ -187,6 +189,12 @@ pthread_rwlock_wrlock(pthread_rwlock_t *
 	 * waiting readers.
 	 */
 	while ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL)) {
+#ifdef ERRORCHECK
+		if (pthread__started == 0) {
+			pthread_spinunlock(self, &rwlock->ptr_interlock);
+			return EDEADLK;
+		}
+#endif
 		PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep);
 		/* Locking a rwlock is not a cancellation point; don't check */
 		pthread_spinlock(self, &self->pt_statelock);
@@ -332,11 +340,6 @@ pthread_rwlock_timedwrlock(pthread_rwloc
 	    (abs_timeout->tv_sec < 0))
 		return EINVAL;
 
-	if (pthread__started == 0) {
-		pthread__start();
-		pthread__started = 1;
-	}
-
 	self = pthread__self();
 	pthread_spinlock(self, &rwlock->ptr_interlock);
 #ifdef ERRORCHECK
@@ -352,6 +355,12 @@ pthread_rwlock_timedwrlock(pthread_rwloc
 	retval = 0;
 	while (retval == 0 &&
 	    ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL))) {
+#ifdef ERRORCHECK
+		if (pthread__started == 0) {
+			pthread_spinunlock(self, &rwlock->ptr_interlock);
+			return EDEADLK;
+		}
+#endif
 		wait.ptw_thread = self;
 		wait.ptw_rwlock = rwlock;
 		wait.ptw_queue = &rwlock->ptr_wblocked;
Index: sem.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/sem.c,v
retrieving revision 1.8
diff -u -p -r1.8 sem.c
--- sem.c	16 Oct 2005 00:07:24 -0000	1.8
+++ sem.c	18 Oct 2005 13:43:16 -0000
@@ -303,8 +303,19 @@ sem_wait(sem_t *sem)
 	}
 
 	if (pthread__started == 0) {
-		pthread__start();
-		pthread__started = 1;
+		sigset_t set, oset;
+
+		sigfillset(&set);
+		(void) sigprocmask(SIG_SETMASK, &set, &oset);
+		for (;;) {
+			if ((*sem)->usem_count > 0) {
+				break;
+			}
+			(void) sigsuspend(&oset);
+		}
+		(*sem)->usem_count--;
+		(void) sigprocmask(SIG_SETMASK, &oset, NULL);
+		return 0;
 	}
 
 	for (;;) {

--FCuugMFkClbJLl1L--