summaryrefslogtreecommitdiff
path: root/mit-pthreads/patches/mevans
diff options
context:
space:
mode:
Diffstat (limited to 'mit-pthreads/patches/mevans')
-rwxr-xr-xmit-pthreads/patches/mevans642
1 files changed, 642 insertions, 0 deletions
diff --git a/mit-pthreads/patches/mevans b/mit-pthreads/patches/mevans
new file mode 100755
index 00000000000..d5ff2f27610
--- /dev/null
+++ b/mit-pthreads/patches/mevans
@@ -0,0 +1,642 @@
+=A0
+Attached are several patches for pthreads-1_60_beta6. The patches fall
+into 3 catagories:
+
+ 1. Crashes and hangs.
+ 2. Missing functionality (namely flock())
+ 3. Use of POSIX reentrant safe routines.
+
+Most of the patches contain a comment as to why the change was made.
+The one major exception is to fd_kern.c at line 257 (unpatched). The
+change to that line is to fix a "hang" that prevents threads for
+scheduling for an hour if there is no external I/O event.
+
+I also include patches that modify several functions to use POSIX
+reentrant safe routines. I know that MIT pthreads implements routine
+like gethostbyname in a thread safe manner, but we're pretty, um, anal
+about trying to keep our code as portable as possible. By excluding
+using routines that are not reentrant safe according to the PTHREAD
+safe, it's easy for us to stub out the unsafe routines and catch
+non-compliant code. I almost left these patches out, but I'm hoping
+they'll be adopted. :-)
+
+WARNING: None of the MIT pthreads routines that convert floats/doubles
+between their native forms and strings are thread safe! (i.e printf,
+sprintf, fprintf, atod, strtod, etc) I have replacements, but I need to
+check with the author of the replacements and my employer.
+
+Mark Evans
+
+------------69CDAAF52A3566916F8ED01A0
+Content-Disposition: inline; filename="pthreads-1_60_beta6.patch"
+Content-Type: text/plain; charset=us-ascii; name="pthreads-1_60_beta6.patch"
+Content-Transfer-Encoding: 7bit
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/config/config.h.in pthreads-1_60_beta6+/config/config.h.in
+*** pthreads-1_60_beta6/config/config.h.in Thu Mar 21 21:30:04 1996
+--- pthreads-1_60_beta6+/config/config.h.in Sat Mar 15 14:08:55 1997
+***************
+*** 137,142 ****
+--- 137,145 ----
+ /* Define if you have the syscall_ftruncate function. */
+ #undef HAVE_SYSCALL_FTRUNCATE
+
++ /* Define if you have the syscall_flock function. */
++ #undef HAVE_SYSCALL_FLOCK
++
+ /* Define if you have the syscall_getdents function. */
+ #undef HAVE_SYSCALL_GETDENTS
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/config/configure.in pthreads-1_60_beta6+/config/configure.in
+*** pthreads-1_60_beta6/config/configure.in Wed Nov 13 14:03:08 1996
+--- pthreads-1_60_beta6+/config/configure.in Sat Mar 15 14:08:55 1997
+***************
+*** 241,247 ****
+
+ PTHREADS_CHECK_SYSCALLS(open write read creat close fcntl lseek dup2 dup pipe
+ fchmod fchown execve fstat lstat link unlink chdir chown chmod stat
+! rename select getdtablesize ioctl ftruncate
+ dnl - signals
+ sigsuspend sigaction sigpause sigprocmask ksigaction
+ dnl - directory reading
+--- 241,247 ----
+
+ PTHREADS_CHECK_SYSCALLS(open write read creat close fcntl lseek dup2 dup pipe
+ fchmod fchown execve fstat lstat link unlink chdir chown chmod stat
+! rename select getdtablesize ioctl ftruncate flock
+ dnl - signals
+ sigsuspend sigaction sigpause sigprocmask ksigaction
+ dnl - directory reading
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/gen/directory.c pthreads-1_60_beta6+/gen/directory.c
+*** pthreads-1_60_beta6/gen/directory.c Sat May 20 10:55:34 1995
+--- pthreads-1_60_beta6+/gen/directory.c Sat Mar 15 14:08:55 1997
+***************
+*** 251,262 ****
+--- 251,266 ----
+ /*
+ * Seek to an entry in a directory.
+ * _seekdir is in telldir.c so that it can share opaque data structures.
++ *
++ * Use the POSIX reentrant safe readdir_r to simplify varifying POSIX
++ * thread-safe compliance.
+ */
+ void seekdir(DIR * dirp, long loc)
+ {
+ register struct ddloc ** prevlp;
+ register struct ddloc * lp;
+ struct dirent * dp;
++ struct dirent de;
+
+ pthread_mutex_lock (dirp->dd_lock);
+ prevlp = (struct ddloc **)&(dirp->dd_ddloc);
+***************
+*** 277,283 ****
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+! if (!(dp = readdir(dirp))) {
+ *prevlp = lp->loc_next;
+ break;
+ }
+--- 281,287 ----
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+! if (readdir_r(dirp, &de, &dp)) {
+ *prevlp = lp->loc_next;
+ break;
+ }
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/gen/getcwd.c pthreads-1_60_beta6+/gen/getcwd.c
+*** pthreads-1_60_beta6/gen/getcwd.c Sat Sep 2 17:39:30 1995
+--- pthreads-1_60_beta6+/gen/getcwd.c Sat Mar 15 14:08:55 1997
+***************
+*** 50,67 ****
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
+
+ char *
+ getcwd(pt, size)
+ char *pt;
+ size_t size;
+ {
+- register struct dirent *dp;
+ register DIR *dir;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+--- 50,71 ----
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
+
++ /* Only use reentrant safe routines to simplify varifying POSIX thread-safe
++ * compliance. (mevans).
++ */
+ char *
+ getcwd(pt, size)
+ char *pt;
+ size_t size;
+ {
+ register DIR *dir;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
++ struct dirent *dp;
++ struct dirent de;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+***************
+*** 166,179 ****
+ save_errno = 0;
+ if (s.st_dev == dev) {
+ for (;;) {
+! if (!(dp = readdir(dir)))
+ goto notfound;
+ if (dp->d_fileno == ino)
+ break;
+ }
+ } else
+ for (;;) {
+! if (!(dp = readdir(dir)))
+ goto notfound;
+ if (ISDOT(dp))
+ continue;
+--- 170,183 ----
+ save_errno = 0;
+ if (s.st_dev == dev) {
+ for (;;) {
+! if (readdir_r(dir, &de, &dp))
+ goto notfound;
+ if (dp->d_fileno == ino)
+ break;
+ }
+ } else
+ for (;;) {
+! if (readdir_r(dir, &de, &dp))
+ goto notfound;
+ if (ISDOT(dp))
+ continue;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/include/syslog.h pthreads-1_60_beta6+/include/syslog.h
+*** pthreads-1_60_beta6/include/syslog.h Mon Sep 26 21:26:29 1994
+--- pthreads-1_60_beta6+/include/syslog.h Sat Mar 15 14:08:56 1997
+***************
+*** 9,14 ****
+--- 9,16 ----
+ #ifndef SYSLOG_H
+ #define SYSLOG_H
+
++ /* Added __[BEGIN/END]_DECLS so this file would work with C++. (mevans) */
++ #include <sys/cdefs.h>
+ #include <stdarg.h>
+
+ /* Discipline: openlog(), closelog(), and setlogmask() are not thread-safe
+***************
+*** 84,95 ****
+--- 86,101 ----
+ #define LOG_NDELAY 0x08 /* don't delay open */
+ #define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */
+
++ __BEGIN_DECLS
++
+ /* Syslogging functions. */
+ void syslog(int pri, char *fmt, ...);
+ void vsyslog(int pri, char *fmt, va_list args);
+ void openlog(char *ident, int logstat, int logfac);
+ void closelog(void);
+ int setlogmask(int pmask);
++
++ __END_DECLS
+
+ #endif
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/machdep/engine-i386-linux-1.0.c pthreads-1_60_beta6+/machdep/engine-i386-linux-1.0.c
+*** pthreads-1_60_beta6/machdep/engine-i386-linux-1.0.c Mon Oct 21 20:39:13 1996
+--- pthreads-1_60_beta6+/machdep/engine-i386-linux-1.0.c Sat Mar 15 14:08:56 1997
+***************
+*** 142,147 ****
+--- 142,149 ----
+ * machdep_pthread_start().
+ */
+ machdep_pthread->machdep_state->__pc = (char *)machdep_pthread_start;
++ machdep_pthread->machdep_state->__bp = (char *)0;/* So the backtrace
++ * is sensible (mevans) */
+
+ /* Stack starts high and builds down. */
+ machdep_pthread->machdep_state->__sp =
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/machdep/syscall-i386-linux-1.0.S pthreads-1_60_beta6+/machdep/syscall-i386-linux-1.0.S
+*** pthreads-1_60_beta6/machdep/syscall-i386-linux-1.0.S Mon Oct 21 22:17:32 1996
+--- pthreads-1_60_beta6+/machdep/syscall-i386-linux-1.0.S Sat Mar 15 14:08:56 1997
+***************
+*** 148,156 ****
+ /* =========================================================================
+ * exit 1 select 82
+ * fork 2 socketcall 102
+! * read 3 readv 145
+! * write 4 writev 146
+! * open 5
+ * creat 8
+ * link 9
+ * unlink 10
+--- 148,156 ----
+ /* =========================================================================
+ * exit 1 select 82
+ * fork 2 socketcall 102
+! * read 3 flock 143
+! * write 4 readv 145
+! * open 5 writev 146
+ * creat 8
+ * link 9
+ * unlink 10
+***************
+*** 390,394 ****
+--- 390,401 ----
+ */
+ #ifdef HAVE_SYSCALL_WRITEV
+ SYSCALL3(writev)
++ #endif
++
++ /* ==========================================================================
++ * machdep_sys_flock()
++ */
++ #ifdef HAVE_SYSCALL_FLOCK
++ SYSCALL2(flock)
+ #endif
+
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/net/gethostbyname.c pthreads-1_60_beta6+/net/gethostbyname.c
+*** pthreads-1_60_beta6/net/gethostbyname.c Mon Apr 22 22:41:21 1996
+--- pthreads-1_60_beta6+/net/gethostbyname.c Sat Mar 15 14:08:58 1997
+***************
+*** 146,161 ****
+ {
+ char **alias;
+ FILE *fp = NULL;
+
+ pthread_mutex_lock(&host_iterate_lock);
+ sethostent(0);
+! while ((result = gethostent_r(result, buf, bufsize, errval)) != NULL) {
+ /* Check the entry's name and aliases against the given name. */
+ if (strcasecmp(result->h_name, name) == 0)
+ break;
+ for (alias = result->h_aliases; *alias; alias++) {
+! if (strcasecmp(*alias, name) == 0)
+ break;
+ }
+ }
+ pthread_mutex_unlock(&host_iterate_lock);
+--- 146,166 ----
+ {
+ char **alias;
+ FILE *fp = NULL;
++ int fFound = FALSE;
+
+ pthread_mutex_lock(&host_iterate_lock);
+ sethostent(0);
+! while (!fFound && (result = gethostent_r(result, buf, bufsize, errval))
+! != NULL) {
+ /* Check the entry's name and aliases against the given name. */
+ if (strcasecmp(result->h_name, name) == 0)
+ break;
+ for (alias = result->h_aliases; *alias; alias++) {
+! if (strcasecmp(*alias, name) == 0) {
+! /* fFound will exit while loop. (mevans). */
+! fFound = TRUE;
+ break;
++ }
+ }
+ }
+ pthread_mutex_unlock(&host_iterate_lock);
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/net/res_debug.c pthreads-1_60_beta6+/net/res_debug.c
+*** pthreads-1_60_beta6/net/res_debug.c Thu Feb 23 22:42:35 1995
+--- pthreads-1_60_beta6+/net/res_debug.c Sat Mar 15 14:08:58 1997
+***************
+*** 375,380 ****
+--- 375,383 ----
+
+ /*
+ * Print resource record fields in human readable form.
++ *
++ * Removed calls to non-reentrant routines to simplify varifying
++ * POSIX thread-safe implementations. (mevans).
+ */
+ char *
+ p_rr(cp, msg, file)
+***************
+*** 386,391 ****
+--- 389,395 ----
+ char *cp1, *cp2;
+ u_long tmpttl, t;
+ int lcnt;
++ char buf[32];
+
+ if ((cp = p_fqname(cp, msg, file)) == NULL)
+ return (NULL); /* compression error */
+***************
+*** 413,426 ****
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ if (dlen == 4) {
+! fprintf(file,"\t%s", inet_ntoa(inaddr));
+ cp += dlen;
+ } else if (dlen == 7) {
+ char *address;
+ u_char protocol;
+ u_short port;
+
+! address = inet_ntoa(inaddr);
+ cp += sizeof(inaddr);
+ protocol = *(u_char*)cp;
+ cp += sizeof(u_char);
+--- 417,432 ----
+ case C_HS:
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ if (dlen == 4) {
+! fprintf(file,"\t%s",
+! inet_ntoa_r(inaddr, buf, sizeof(buf)));
+ cp += dlen;
+ } else if (dlen == 7) {
+ char *address;
+ u_char protocol;
+ u_short port;
+
+! address = inet_ntoa_r(inaddr,
+! buf, sizeof(buf));
+ cp += sizeof(inaddr);
+ protocol = *(u_char*)cp;
+ cp += sizeof(u_char);
+***************
+*** 524,530 ****
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ cp += sizeof(u_long);
+ fprintf(file, "\t%s %s ( ",
+! inet_ntoa(inaddr),
+ deproto((int) *cp));
+ cp += sizeof(u_char);
+ n = 0;
+--- 530,536 ----
+ bcopy(cp, (char *)&inaddr, sizeof(inaddr));
+ cp += sizeof(u_long);
+ fprintf(file, "\t%s %s ( ",
+! inet_ntoa_r(inaddr, buf, sizeof(buf)),
+ deproto((int) *cp));
+ cp += sizeof(u_char);
+ n = 0;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/fd_kern.c pthreads-1_60_beta6+/pthreads/fd_kern.c
+*** pthreads-1_60_beta6/pthreads/fd_kern.c Tue Oct 1 12:26:48 1996
+--- pthreads-1_60_beta6+/pthreads/fd_kern.c Sat Mar 15 14:09:00 1997
+***************
+*** 215,221 ****
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+!
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+--- 215,221 ----
+ * Called when there is no active thread to run.
+ */
+ extern struct timeval __fd_kern_wait_timeout;
+! extern volatile sig_atomic_t sig_to_process;
+ void fd_kern_wait()
+ {
+ fd_set fd_set_read, fd_set_write, fd_set_except;
+***************
+*** 254,260 ****
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+
+--- 254,260 ----
+
+ machdep_unset_thread_timer(NULL);
+ __fd_kern_wait_timeout.tv_usec = 0;
+! __fd_kern_wait_timeout.tv_sec = (sig_to_process) ? 0 : 3600;
+
+ machdep_sys_sigprocmask(SIG_UNBLOCK, &sig_to_block, &oset);
+
+***************
+*** 726,731 ****
+--- 726,753 ----
+ return(ret);
+ }
+
++ #if defined (HAVE_SYSCALL_FLOCK)
++ /* ==========================================================================
++ * flock()
++ *
++ * Added (mevans)
++ */
++ int flock(int fd, int operation)
++ {
++ int ret;
++
++ if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) {
++ if ((ret = machdep_sys_flock(fd_table[fd]->fd.i,
++ operation)) < OK) {
++ SET_ERRNO(-ret);
++ ret = NOTOK;
++ }
++ fd_unlock(fd, FD_RDWR);
++ }
++ return(ret);
++ }
++ #endif
++
+ /* ==========================================================================
+ * pipe()
+ */
+***************
+*** 1126,1132 ****
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+ SO_ERROR, &ret, &tmpnamelen);
+! SET_ERRNO(-ret);
+ ret = NOTOK;
+ }
+ } else {
+--- 1148,1155 ----
+ /* Get the error, this function should not fail */
+ machdep_sys_getsockopt(fd_table[fd]->fd.i, SOL_SOCKET,
+ SO_ERROR, &ret, &tmpnamelen);
+! /* ret is already positive (mevans) */
+! SET_ERRNO(ret);
+ ret = NOTOK;
+ }
+ } else {
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/malloc.c pthreads-1_60_beta6+/pthreads/malloc.c
+*** pthreads-1_60_beta6/pthreads/malloc.c Thu Mar 9 21:06:43 1995
+--- pthreads-1_60_beta6+/pthreads/malloc.c Sat Mar 15 14:09:00 1997
+***************
+*** 196,204 ****
+ else
+ n = n - x;
+ if (n) {
+! if (sbrk(n) == (char *)-1)
+ return (NULL);
+ }
+ bucket = 0;
+ amt = 8;
+ while (pagesz > amt) {
+--- 196,207 ----
+ else
+ n = n - x;
+ if (n) {
+! if (sbrk(n) == (char *)-1) {
+! /* Unlock before returning (mevans) */
+! pthread_mutex_unlock(mutex);
+ return (NULL);
+ }
++ }
+ bucket = 0;
+ amt = 8;
+ while (pagesz > amt) {
+***************
+*** 363,366 ****
+--- 366,382 ----
+ free(cp);
+
+ return (res);
++ }
++ /* ==========================================================================
++ * calloc()
++ *
++ * Added to ensure pthread's allocation is used (mevans).
++ */
++ void *calloc(size_t nmemb, size_t size)
++ {
++ void *p;
++ size *= nmemb;
++ p = malloc(size);
++ if (p) memset(p, 0, size);
++ return (p);
+ }
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/select.c pthreads-1_60_beta6+/pthreads/select.c
+*** pthreads-1_60_beta6/pthreads/select.c Sat Jul 6 21:58:55 1996
+--- pthreads-1_60_beta6+/pthreads/select.c Sat Mar 15 14:09:00 1997
+***************
+*** 165,176 ****
+ pthread_resched_resume(PS_SELECT_WAIT);
+
+ /* We're awake */
+- CLEAR_PF_DONE_EVENT(pthread_run);
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ ret = OK;
+ } else {
+ ret = data.nfds;
+ }
+ } else {
+ pthread_resched_resume(PS_SELECT_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+--- 165,180 ----
+ pthread_resched_resume(PS_SELECT_WAIT);
+
+ /* We're awake */
+ if (sleep_cancel(pthread_run) == NOTOK) {
+ ret = OK;
+ } else {
+ ret = data.nfds;
+ }
++ /* Moving this after the sleep_cancel() seemed
++ * to fix intermittent crashes during heavy
++ * socket use. (mevans)
++ */
++ CLEAR_PF_DONE_EVENT(pthread_run);
+ } else {
+ pthread_resched_resume(PS_SELECT_WAIT);
+ CLEAR_PF_DONE_EVENT(pthread_run);
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/pthreads/signal.c pthreads-1_60_beta6+/pthreads/signal.c
+*** pthreads-1_60_beta6/pthreads/signal.c Tue Mar 12 21:33:17 1996
+--- pthreads-1_60_beta6+/pthreads/signal.c Sat Mar 15 14:09:00 1997
+***************
+*** 65,71 ****
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! static sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+--- 65,71 ----
+ */
+
+ static sig_atomic_t signum_to_process[SIGMAX + 1] = { 0, };
+! volatile sig_atomic_t sig_to_process = 0;
+
+ /* static volatile sigset_t sig_to_process; */
+ static volatile int sig_count = 0;
+***************
+*** 303,309 ****
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were sleeping */
+! sigdefault(sig);
+ break;
+ }
+ break;
+--- 303,317 ----
+ break;
+ case NOTOK:
+ /* Do the registered action, no threads were sleeping */
+! /* There is a timing window that gets
+! * here when no threads are on the
+! * sleep queue. This is a quick fix.
+! * The real problem is possibly related
+! * to heavy use of condition variables
+! * with time outs.
+! * (mevans)
+! *sigdefault(sig);
+! */
+ break;
+ }
+ break;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/stdio/setvbuf.c pthreads-1_60_beta6+/stdio/setvbuf.c
+*** pthreads-1_60_beta6/stdio/setvbuf.c Sat Sep 3 20:58:36 1994
+--- pthreads-1_60_beta6+/stdio/setvbuf.c Sat Mar 15 14:09:00 1997
+***************
+*** 142,148 ****
+ flags |= __SLBF;
+ if (flags & __SRW)
+ flags &= ~(__SRD | __SWR);
+! fp->_w = 0;
+ fp->_flags = flags;
+ fp->_bf._base = fp->_p = (unsigned char *)buf;
+ fp->_bf._size = size;
+--- 142,148 ----
+ flags |= __SLBF;
+ if (flags & __SRW)
+ flags &= ~(__SRD | __SWR);
+! fp->_w = size; /* Was 0 (mevans) */
+ fp->_flags = flags;
+ fp->_bf._base = fp->_p = (unsigned char *)buf;
+ fp->_bf._size = size;
+diff -c -b -r -d -I .*$Id:.* pthreads-1_60_beta6/stdlib/system.c pthreads-1_60_beta6+/stdlib/system.c
+*** pthreads-1_60_beta6/stdlib/system.c Wed Apr 24 21:18:56 1996
+--- pthreads-1_60_beta6+/stdlib/system.c Sat Mar 15 14:09:01 1997
+***************
+*** 62,68 ****
+ argp[2] = (char *) command;
+ sigemptyset(&tmp_mask);
+ sigaddset(&tmp_mask, SIGCHLD);
+! pthread_sigmask(SIG_BLOCK, tmp_mask, &old_mask);
+ switch(pid = fork()) {
+ case -1: /* error */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
+--- 62,69 ----
+ argp[2] = (char *) command;
+ sigemptyset(&tmp_mask);
+ sigaddset(&tmp_mask, SIGCHLD);
+! /* Pass the address of tmp_mask to avoid a sigfault. (mevans). */
+! pthread_sigmask(SIG_BLOCK, &tmp_mask, &old_mask);
+ switch(pid = fork()) {
+ case -1: /* error */
+ (void)pthread_sigmask(SIG_SETMASK, &old_mask, NULL);