From 93488dfe1eac324a4525b6e6d4b407d925f2ac8b Mon Sep 17 00:00:00 2001 From: Kevin Tew Date: Tue, 1 Dec 2009 17:26:54 +0000 Subject: [PATCH] [Places] Fix SIGCHLD svn: r17140 --- src/mzscheme/src/env.c | 8 +- src/mzscheme/src/mzmark.c | 2 +- src/mzscheme/src/mzrt.c | 3 +- src/mzscheme/src/places.c | 155 +++++++++++++++++++++++++++++++++-- src/mzscheme/src/port.c | 160 +++++++++++++++++++++++++++---------- src/mzscheme/src/print.c | 2 + src/mzscheme/src/schpriv.h | 5 +- src/mzscheme/src/thread.c | 6 +- 8 files changed, 287 insertions(+), 54 deletions(-) diff --git a/src/mzscheme/src/env.c b/src/mzscheme/src/env.c index d4978d0cb4..73ce18a60e 100644 --- a/src/mzscheme/src/env.c +++ b/src/mzscheme/src/env.c @@ -356,8 +356,10 @@ Scheme_Env *scheme_engine_instance_init() { #endif #if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES) + scheme_places_block_child_signal(); + GC_switch_out_master_gc(); - spawn_master_scheme_place(); + scheme_spawn_master_place(); #endif place_instance_init_pre_kernel(stack_base); @@ -367,7 +369,7 @@ Scheme_Env *scheme_engine_instance_init() { #if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES) { - int signal_fd; + int *signal_fd; signal_fd = scheme_get_signal_handle(); GC_set_put_external_event_fd(signal_fd); } @@ -508,7 +510,7 @@ static Scheme_Env *place_instance_init_post_kernel(int initial_main_os_thread) { Scheme_Env *scheme_place_instance_init(void *stack_base) { Scheme_Env *env; #if defined(MZ_PRECISE_GC) && defined(MZ_USE_PLACES) - int signal_fd; + int *signal_fd; GC_construct_child_gc(); #endif place_instance_init_pre_kernel(stack_base); diff --git a/src/mzscheme/src/mzmark.c b/src/mzscheme/src/mzmark.c index 5ff15d2952..4e97078bc5 100644 --- a/src/mzscheme/src/mzmark.c +++ b/src/mzscheme/src/mzmark.c @@ -3582,7 +3582,7 @@ static int mark_input_fd_FIXUP(void *p) { #endif -#if defined(UNIX_PROCESSES) +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) static int mark_system_child_SIZE(void *p) { return gcBYTES_TO_WORDS(sizeof(System_Child)); diff --git a/src/mzscheme/src/mzrt.c b/src/mzscheme/src/mzrt.c index 9bbe396fb0..4cdad99dc9 100644 --- a/src/mzscheme/src/mzrt.c +++ b/src/mzscheme/src/mzrt.c @@ -72,7 +72,8 @@ static void rungdb() { case 'd': snprintf(outbuffer, 100, "xterm -e gdb ./mzscheme3m %d &", pid); fprintf(stderr, "%s\n", outbuffer); - system(outbuffer); + if(system(outbuffer)) + fprintf(stderr, "system failed\n"); break; case 'e': default: diff --git a/src/mzscheme/src/places.c b/src/mzscheme/src/places.c index 7a17ae0a9b..ae92403141 100644 --- a/src/mzscheme/src/places.c +++ b/src/mzscheme/src/places.c @@ -39,6 +39,7 @@ static Scheme_Object *not_implemented(int argc, Scheme_Object **argv) # ifdef MZ_PRECISE_GC static void register_traversers(void) { } + # endif #endif @@ -133,10 +134,151 @@ Scheme_Object *scheme_place(int argc, Scheme_Object *args[]) { } #ifdef MZ_PRECISE_GC +/*============= SIGNAL HANDLER =============*/ +#include +#include +#include +#include + + +static void error_info() { + char *erstr; + erstr = strerror(errno); + printf("errno %i %s\n", errno, erstr); +} + +typedef struct Child_Status { + int pid; + int status; + void *signal_fd; + struct Child_Status *next; +} Child_Status; + +static Child_Status *child_statuses = NULL; +static mzrt_mutex* child_status_lock = NULL; + +static void add_child_status(int pid, int status) { + Child_Status *st; + st = malloc(sizeof(Child_Status)); + st->pid = pid; + st->signal_fd = NULL; + st->status = status; + + mzrt_mutex_lock(child_status_lock); + st->next = child_statuses; + child_statuses = st; + mzrt_mutex_unlock(child_status_lock); +} + +static int raw_get_child_status(int pid, int *status) { + Child_Status *st; + Child_Status *prev; + int found = 0; + + for (st = child_statuses, prev = NULL; st; prev = st, st = st->next) { + if (st->pid == pid) { + *status = st->status; + found = 1; + if (prev) { + prev->next = st->next; + } + else { + child_statuses = st->next; + } + free(st); + break; + } + } + return found; +} + +int scheme_get_child_status(int pid, int *status) { + int found = 0; + mzrt_mutex_lock(child_status_lock); + found = raw_get_child_status(pid, status); + mzrt_mutex_unlock(child_status_lock); + /* printf("scheme_get_child_status found %i pid %i status %i\n", found, pid, *status); */ + return found; +} + +int scheme_places_register_child(int pid, void *signal_fd, int *status) { + int found = 0; + + mzrt_mutex_lock(child_status_lock); + found = raw_get_child_status(pid, status); + if (!found) { + Child_Status *st; + st = malloc(sizeof(Child_Status)); + st->pid = pid; + st->signal_fd = signal_fd; + st->status = 0; + + st->next = child_statuses; + child_statuses = st; + } + mzrt_mutex_unlock(child_status_lock); + return found; +} + +static void *mz_proc_thread_signal_worker(void *data) { + int status; + int pid; + sigset_t set; + //GC_CAN_IGNORE siginfo_t info; + { + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); + } + + while(1) { + int rc; + int signalid; + do { + rc = sigwait(&set, &signalid); + if (rc == -1) { + if (errno != EINTR ) { + error_info(); + } + } + } while (rc == -1 && errno == EINTR); + + pid = waitpid((pid_t)-1, &status, WNOHANG); + if (pid == -1) { + char *erstr; + erstr = strerror(errno); + /* printf("errno %i %s\n", errno, erstr); */ + } + else { + /* printf("SIGCHILD pid %i with status %i %i\n", pid, status, WEXITSTATUS(status)); */ + add_child_status(pid, status); + } + }; + return NULL; +} + + +void scheme_places_block_child_signal() { + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + pthread_sigmask(SIG_BLOCK, &set, NULL); + } + + { + mz_proc_thread *signal_thread; + mzrt_mutex_create(&child_status_lock); + signal_thread = mz_proc_thread_create(mz_proc_thread_signal_worker, NULL); + mz_proc_thread_detach(signal_thread); + } +} + +/*============= THREAD JOIN HANDLER =============*/ typedef struct { mz_proc_thread *proc_thread; Scheme_Place *waiting_place; - int wake_fd; + int *wake_fd; int ready; long rc; } proc_thread_wait_data; @@ -149,7 +291,7 @@ static void *mz_proc_thread_wait_worker(void *data) { rc = mz_proc_thread_wait(wd->proc_thread); wd->rc = (long) rc; wd->ready = 1; - scheme_signal_received_at(&wd->wake_fd); + scheme_signal_received_at(wd->wake_fd); return NULL; } @@ -171,7 +313,7 @@ static Scheme_Object *scheme_place_wait(int argc, Scheme_Object *args[]) { Scheme_Object *rc; mz_proc_thread *worker_thread; Scheme_Place *waiting_place; - int wake_fd; + int *wake_fd; proc_thread_wait_data *wd; wd = (proc_thread_wait_data*) malloc(sizeof(proc_thread_wait_data)); @@ -285,7 +427,7 @@ static void *place_start_proc(void *data_arg) { stack_base = PROMPT_STACK(stack_base); place_data = (Place_Start_Data *) data_arg; - printf("Startin place: proc thread id%u\n", ptid); + /* printf("Startin place: proc thread id%u\n", ptid); */ /* create pristine THREAD_LOCAL variables*/ null_out_runtime_globals(); @@ -328,6 +470,8 @@ Scheme_Object *scheme_places_deep_copy_in_master(Scheme_Object *so) { #ifdef MZ_PRECISE_GC static void* scheme_master_place_handlemsg(int msg_type, void *msg_payload); + +#if 0 static void *master_scheme_place(void *data) { mz_proc_thread *myself; myself = proc_thread_self; @@ -345,6 +489,7 @@ static void *master_scheme_place(void *data) { } return NULL; } +#endif static void* scheme_master_place_handlemsg(int msg_type, void *msg_payload) { @@ -390,7 +535,7 @@ void* scheme_master_fast_path(int msg_type, void *msg_payload) { } -void spawn_master_scheme_place() { +void scheme_spawn_master_place() { mzrt_proc_first_thread_init(); diff --git a/src/mzscheme/src/port.c b/src/mzscheme/src/port.c index be14d99b34..b265a2accd 100644 --- a/src/mzscheme/src/port.c +++ b/src/mzscheme/src/port.c @@ -169,7 +169,7 @@ int scheme_stupid_windows_machine; /******************** Unix Subprocesses ********************/ -#if defined(UNIX_PROCESSES) +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) /* For process & system: */ typedef struct System_Child { MZTAG_IF_REQUIRED @@ -186,6 +186,10 @@ typedef struct Scheme_Subprocess { Scheme_Object so; void *handle; int pid; +#if defined(UNIX_PROCESSES) && defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) + short done; + int status; +#endif } Scheme_Subprocess; #ifdef USE_FD_PORTS @@ -486,7 +490,7 @@ scheme_init_port (Scheme_Env *env) REGISTER_SO(scheme_null_output_port_type); REGISTER_SO(scheme_redirect_output_port_type); -#if defined(UNIX_PROCESSES) +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) REGISTER_SO(scheme_system_children); #endif @@ -6787,7 +6791,7 @@ static int MyPipe(int *ph, int near_index) { /**************** Unix: signal stuff ******************/ -#if defined(UNIX_PROCESSES) +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) # define WAITANY(s) waitpid((pid_t)-1, s, WNOHANG) @@ -6800,6 +6804,7 @@ static int need_to_check_children; void scheme_block_child_signals(int block) XFORM_SKIP_PROC { +#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) sigset_t sigs; sigemptyset(&sigs); @@ -6808,6 +6813,7 @@ void scheme_block_child_signals(int block) sigaddset(&sigs, SIGPROF); #endif sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL); +#endif } static void child_done(int ingored) @@ -6825,6 +6831,7 @@ static int sigchld_installed = 0; static void init_sigchld(void) { +#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) if (!sigchld_installed) { /* Catch child-done signals */ START_XFORM_SKIP; @@ -6833,6 +6840,7 @@ static void init_sigchld(void) sigchld_installed = 1; } +#endif } static void check_child_done() @@ -7073,24 +7081,47 @@ scheme_make_redirect_output_port(Scheme_Object *port) #if defined(UNIX_PROCESSES) || defined(WINDOWS_PROCESSES) -static int subp_done(Scheme_Object *sp) +static int subp_done(Scheme_Object *so) { - void *sci = ((Scheme_Subprocess *)sp)->handle; + Scheme_Subprocess *sp; + sp = (Scheme_Subprocess*) so; #if defined(UNIX_PROCESSES) - System_Child *sc = (System_Child *)sci; - check_child_done(); - return sc->done; -#endif -#ifdef WINDOWS_PROCESSES - DWORD w; - if (sci) { - if (GetExitCodeProcess((HANDLE)sci, &w)) - return w != STILL_ACTIVE; +# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) + { + int status; + if(! sp->done) { + if(scheme_get_child_status(((Scheme_Subprocess *)sp)->pid, &status)) { + sp->done = 1; + sp->status = status; + return 1; + } + return 0; + } else return 1; - } else - return 1; + } +# else + { + System_Child *sc; + sc = ((System_Child *) ((Scheme_Subprocess *)sp)->handle); + check_child_done(); + return sc->done; + } +# endif +#endif +#ifdef WINDOWS_PROCESSES + { + HANDLE sci = (HANDLE) ((Scheme_Subprocess *)sp)->handle; + DWORD w; + if (sci) { + if (GetExitCodeProcess(sci, &w)) + return w != STILL_ACTIVE; + else + return 1; + } else + return 1; + } #endif } @@ -7116,14 +7147,23 @@ static Scheme_Object *subprocess_status(int argc, Scheme_Object **argv) int going = 0, status = MZ_FAILURE_STATUS; #if defined(UNIX_PROCESSES) - System_Child *sc = (System_Child *)sp->handle; - - check_child_done(); - - if (sc->done) - status = sc->status; - else +# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) + if (sp->done) + status = sp->status; + else { + if(!scheme_get_child_status(((Scheme_Subprocess *)sp)->pid, &status)) { going = 1; + } + } +# else + System_Child *sc = (System_Child *)sp->handle; + check_child_done(); + + if (sc->done) + status = sc->status; + else + going = 1; +# endif #else # ifdef WINDOWS_PROCESSES DWORD w; @@ -7189,23 +7229,34 @@ static Scheme_Object *subprocess_kill(int argc, Scheme_Object **argv) Scheme_Subprocess *sp = (Scheme_Subprocess *)argv[0]; #if defined(UNIX_PROCESSES) - { - System_Child *sc = (System_Child *)sp->handle; - - check_child_done(); - - while (1) { - if (sc->done) - return scheme_void; - - if (!kill(sp->pid, SCHEME_TRUEP(argv[1]) ? SIGKILL : SIGINT)) - return scheme_void; - - if (errno != EINTR) - break; - /* Otherwise we were interrupted. Try `kill' again. */ - } +# if defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC) + { + int status; + if (sp->done) + return scheme_void; + if(scheme_get_child_status(sp->pid, &status)) { + return scheme_void; } + } +# else + { + System_Child *sc = (System_Child *)sp->handle; + + check_child_done(); + if (sc->done) + return scheme_void; + } +# endif + + while (1) { + + if (!kill(sp->pid, SCHEME_TRUEP(argv[1]) ? SIGKILL : SIGINT)) + return scheme_void; + + if (errno != EINTR) + break; + /* Otherwise we were interrupted. Try `kill' again. */ + } #else if (SCHEME_TRUEP(argv[1])) { DWORD w; @@ -7369,6 +7420,16 @@ static long mz_spawnv(char *command, const char * const *argv, static void close_subprocess_handle(void *sp, void *ignored) { Scheme_Subprocess *subproc = (Scheme_Subprocess *)sp; + #if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) + { + int status; + int pid = ((Scheme_Subprocess *)sp)->pid; + scheme_get_child_status(pid, &status) + /* printf("close_subprocess_handle pid %i status %i\n", pid status); */ + + } + #endif + CloseHandle(subproc->handle); } @@ -7387,7 +7448,9 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) char **argv; Scheme_Object *in, *out, *err; #if defined(UNIX_PROCESSES) +# if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) System_Child *sc; +# endif int fork_errno = 0; #else void *sc = 0; @@ -7609,6 +7672,7 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) /*--------------------------------------*/ { +#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) init_sigchld(); sc = MALLOC_ONE_RT(System_Child); @@ -7619,13 +7683,25 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) sc->done = 0; scheme_block_child_signals(1); +#endif pid = fork(); if (pid > 0) { +#if defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC) + { + int *signal_fd; + int status; + signal_fd = scheme_get_signal_handle(); + scheme_places_register_child(pid, signal_fd, &status); + + /* printf("SUBPROCESS %i\n", pid); */ + } +#else sc->next = scheme_system_children; scheme_system_children = sc; sc->id = pid; +#endif } else if (!pid) { #ifdef USE_ITIMER /* Turn off the timer. */ @@ -7659,7 +7735,9 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) fork_errno = errno; } +#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) scheme_block_child_signals(0); +#endif } switch (pid) @@ -7807,7 +7885,9 @@ static Scheme_Object *subprocess(int c, Scheme_Object *args[]) subproc = MALLOC_ONE_TAGGED(Scheme_Subprocess); subproc->so.type = scheme_subprocess_type; +#if !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) subproc->handle = (void *)sc; +#endif subproc->pid = pid; # if defined(WINDOWS_PROCESSES) scheme_add_finalizer(subproc, close_subprocess_handle, NULL); @@ -8781,7 +8861,7 @@ static void register_traversers(void) GC_REG_TRAV(scheme_rt_input_fd, mark_input_fd); #endif -#if defined(UNIX_PROCESSES) +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined (MZ_PRECISE_GC)) GC_REG_TRAV(scheme_rt_system_child, mark_system_child); #endif diff --git a/src/mzscheme/src/print.c b/src/mzscheme/src/print.c index 6a960455ea..5c797bb912 100644 --- a/src/mzscheme/src/print.c +++ b/src/mzscheme/src/print.c @@ -539,6 +539,7 @@ static int check_cycles(Scheme_Object *obj, int for_write, Scheme_Hash_Table *ht version takes to long, we back out to the general case. (We don't even check for stack overflow, so keep the max limit low.) */ +#if !defined(MZ_USE_PLACES) static int check_cycles_fast(Scheme_Object *obj, PrintParams *pp, int *fast_checker_counter) XFORM_SKIP_PROC { @@ -614,6 +615,7 @@ static int check_cycles_fast(Scheme_Object *obj, PrintParams *pp, int *fast_chec return cycle; } +#endif #ifdef DO_STACK_CHECK static void setup_graph_table(Scheme_Object *obj, int for_write, Scheme_Hash_Table *ht, int *counter, PrintParams *pp); diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index ae18b4d728..91d1b32c7e 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -3250,8 +3250,11 @@ typedef struct Scheme_Symbol_Parts { const char *name; } Scheme_Symbol_Parts; -void spawn_master_scheme_place(); +void scheme_spawn_master_place(); void *scheme_master_fast_path(int msg_type, void *msg_payload); +void scheme_places_block_child_signal(); +int scheme_get_child_status(int pid, int *status); +int scheme_places_register_child(int pid, void *signal_fd, int *status); # endif Scheme_Object *scheme_places_deep_copy(Scheme_Object *so); #endif diff --git a/src/mzscheme/src/thread.c b/src/mzscheme/src/thread.c index 7d97d9bfdc..33341d05b8 100644 --- a/src/mzscheme/src/thread.c +++ b/src/mzscheme/src/thread.c @@ -4057,7 +4057,7 @@ void scheme_thread_block(float sleep_time) /* Check scheduled_kills early and often. */ check_scheduled_kills(); -#ifdef UNIX_PROCESSES +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) /* Reap zombie processes: */ scheme_check_child_done(); #endif @@ -7371,7 +7371,7 @@ static void get_ready_for_GC() #ifdef WINDOWS_PROCESSES scheme_suspend_remembered_threads(); #endif -#ifdef UNIX_PROCESSES +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) scheme_block_child_signals(1); #endif @@ -7402,7 +7402,7 @@ static void done_with_GC() #ifdef WINDOWS_PROCESSES scheme_resume_remembered_threads(); #endif -#ifdef UNIX_PROCESSES +#if defined(UNIX_PROCESSES) && !(defined(MZ_USE_PLACES) && defined(MZ_PRECISE_GC)) scheme_block_child_signals(0); #endif