diff --git a/src/acconfig.h b/src/acconfig.h index dc49886cf6a75888cce63943572e9077a55563e9..7cc3b1639ac888165db830b6d1e05abd2c3d72b0 100644 --- a/src/acconfig.h +++ b/src/acconfig.h @@ -1,5 +1,5 @@ /* - * $Id: acconfig.h,v 1.38 1999/03/06 01:55:43 grubba Exp $ + * $Id: acconfig.h,v 1.39 1999/03/08 05:34:34 hubbe Exp $ */ #ifndef MACHINE_H #define MACHINE_H @@ -234,6 +234,18 @@ /* Use poll() instead of select() ? */ #undef HAVE_AND_USE_POLL +/* This works on Solaris or any UNIX where + * waitpid can report ECHILD when running more than one at once + * (or any UNIX where waitpid actually works) + */ +#undef USE_WAIT_THREAD + +/* This works on Linux or any UNIX where + * waitpid works or where threads and signals bugs in + * less annoying ways than Solaris. + */ +#undef USE_SIGCHILD + /* Enable code to handle Out-Of-Band data */ #undef WITH_OOB diff --git a/src/configure.in b/src/configure.in index 008ff670a9792daa6fed4c3b1645d681c21af9b2..4b3c934d728ecca026c53889725d883922813458 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.269 1999/03/07 04:24:49 grubba Exp $") +AC_REVISION("$Id: configure.in,v 1.270 1999/03/08 05:34:35 hubbe Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -180,7 +180,7 @@ if test "$uname_prog" != "no"; then case "$pike_cv_sys_os" in SunOS) case "`uname -r`" in - 5.*) pike_cv_sys_os="Solaris"; + 5.*) pike_cv_sys_os="Solaris" ;; esac ;; esac @@ -588,6 +588,9 @@ fi if test "$pike_cv_sys_os" = "Solaris" ; then AC_DEFINE(SOLARIS) + AC_DEFINE(USE_WAIT_THREAD) +else + AC_DEFINE(USE_SIGCHILD) fi if test ! -d modules/. ; then diff --git a/src/signal_handler.c b/src/signal_handler.c index d154766ecdd41a7486adf7e3515631e7ed90fc5e..86eceb73973cb5feb0eee326f3c04067ca71348f 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -23,7 +23,7 @@ #include "builtin_functions.h" #include <signal.h> -RCSID("$Id: signal_handler.c,v 1.114 1999/03/07 18:07:49 grubba Exp $"); +RCSID("$Id: signal_handler.c,v 1.115 1999/03/08 05:34:37 hubbe Exp $"); #ifdef HAVE_PASSWD_H # include <passwd.h> @@ -102,18 +102,12 @@ RCSID("$Id: signal_handler.c,v 1.114 1999/03/07 18:07:49 grubba Exp $"); /* #define PROC_DEBUG */ #ifndef __NT__ - #define USE_PID_MAPPING - -#ifdef _REENTRANT -#define USE_WAIT_THREAD #else -#define USE_SIGCHILD +#undef USE_WAIT_THREAD +#undef USE_SIGCHILD #endif -#endif - - /* Added so we are able to patch older versions of Pike. */ #ifndef add_ref @@ -666,15 +660,15 @@ void process_done(pid_t pid) #endif #ifdef HAVE_WAITPID -#define WAIT_ANY(STATUS,OPT) waitpid(-1,STATUS,OPT) +#define MY_WAIT_ANY(STATUS,OPT) waitpid(-1,STATUS,OPT) #else #ifdef HAVE_WAIT3 -#define WAIT_ANY(STATUS,OPT) wait3((STATUS),(OPT),0 ) +#define MY_WAIT_ANY(STATUS,OPT) wait3((STATUS),(OPT),0 ) #else #ifdef HAVE_WAIT4 -#define WAIT_ANY(STATUS,OPT) wait4(-1,(STATUS),(OPT),0 ) +#define MY_WAIT_ANY(STATUS,OPT) wait4(-1,(STATUS),(OPT),0 ) #else -#define WAIT_ANY(STATUS,OPT) ((errno=ENOTSUP),-1) +#define MY_WAIT_ANY(STATUS,OPT) ((errno=ENOTSUP),-1) #endif #endif #endif @@ -698,7 +692,7 @@ static RETSIGTYPE receive_sigchild(int signum) try_reap_again: /* We carefully reap what we saw */ - pid=WAIT_ANY(&status, WNOHANG); + pid=MY_WAIT_ANY(&status, WNOHANG); if(pid>0) { @@ -806,32 +800,77 @@ static void report_child(int pid, #ifdef USE_WAIT_THREAD static COND_T process_status_change; static COND_T start_wait_thread; -static int num_pids; +static MUTEX_T wait_thread_mutex; -static void *wait_thread(void *data) +static void do_da_lock(void) { - mt_lock(&interpreter_lock); - while(!num_pids) - co_wait(&start_wait_thread, &interpreter_lock); + mt_lock(&wait_thread_mutex); +} - mt_unlock(&interpreter_lock); +static void do_bi_do_da_lock(void) +{ + fprintf(stderr, "wait thread: This is your wakeup call!\n"); + co_signal(&start_wait_thread); + mt_unlock(&wait_thread_mutex); +} +static void *wait_thread(void *data) +{ + if(pthread_atfork(do_da_lock,do_bi_do_da_lock,0)) + { + perror("pthread atfork"); + exit(1); + } + while(1) { WAITSTATUSTYPE status; + int pid; + + mt_lock(&wait_thread_mutex); + pid=MY_WAIT_ANY(&status, WNOHANG); + + if(pid < 0 && errno==ECHILD) + { +#ifdef PROC_DEBUG + fprintf(stderr, "wait_thread: sleeping\n"); +#endif + co_wait(&start_wait_thread, &wait_thread_mutex); + +#ifdef PROC_DEBUG + fprintf(stderr, "wait_thread: waking up\n"); +#endif + } + + mt_unlock(&wait_thread_mutex); - int pid=WAIT_ANY(&status, 0); + if(pid <= 0) pid=MY_WAIT_ANY(&status, 0); + +#ifdef PROC_DEBUG + fprintf(stderr, "wait thread: pid=%d errno=%d\n",pid,errno); +#endif + if(pid>0) { mt_lock(&interpreter_lock); - num_pids--; report_child(pid, status); co_broadcast(& process_status_change); - while(!num_pids) - co_wait(&start_wait_thread, &interpreter_lock); - mt_unlock(&interpreter_lock); + continue; + } + + if(pid == -1) + { + switch(errno) + { + case EINTR: + case ECHILD: + break; + + default: + fprintf(stderr,"Wait thread: waitpid returned error: %d\n",errno); + } } } } @@ -898,7 +937,7 @@ static void f_pid_status_wait(INT32 args) s=low_mapping_lookup(pid_mapping, &key); if(s && s->type == T_OBJECT && s->u.object == fp->current_object) { - error("Operating system failiuer: Pike lost track of a child, pid=%d, errno=%d, errorcount=%d.\n",pid,err,errorcount); + error("Operating system failiuer: Pike lost track of a child, pid=%d, errno=%d.\n",pid,err); } else @@ -2091,11 +2130,6 @@ void f_create_process(INT32 args) } #endif -#ifdef USE_WAIT_THREAD - if(!(num_pids++)) - co_signal(& start_wait_thread); -#endif - THIS->pid = pid; THIS->state = PROCESS_RUNNING; ref_push_object(fp->current_object); @@ -2418,11 +2452,6 @@ void f_fork(INT32 args) } #endif -#ifdef USE_WAIT_THREAD - if(!(num_pids++)) - co_signal(& start_wait_thread); -#endif - o=low_clone(pid_status_program); call_c_initializers(o); p=(struct pid_status *)get_storage(o,pid_status_program); @@ -2629,16 +2658,13 @@ void init_signals(void) #endif #ifdef USE_WAIT_THREAD - /* FIXME: Isn't it required that SIGCHLD hasn't been set to SIGIGN - * for wait() et al to work? (The process that started pike - * may have set it to SIGIGN). - * /grubba 1999-03-07 - */ - co_init(& process_status_change); - co_init(& start_wait_thread); { - THREAD_T dummy; - th_create_small(&dummy,wait_thread,0); + THREAD_T foo; + co_init(& process_status_change); + co_init(& start_wait_thread); + mt_init(& wait_thread_mutex); + th_create_small(&foo,wait_thread,0); + my_signal(SIGCHLD, SIG_DFL); } #endif @@ -2664,9 +2690,12 @@ void init_signals(void) firstsig=lastsig=0; -#ifndef __NT__ +#ifdef USE_PID_MAPPING pid_mapping=allocate_mapping(2); + +#ifndef USE_WAIT_THREAD pid_mapping->flags|=MAPPING_FLAG_WEAK; +#endif #endif start_new_program();