fix subprocess issues

Fix SIGCHLD suspension for fork()-based file locks (i.e., Solaris).

Also, fix commit ea51d32e, which broke termination of process groups
where the main process terminated before the rest of the group,
because it used sigwait() before the terminate action.
This commit is contained in:
Matthew Flatt 2013-08-09 07:08:45 -06:00
parent d93ce089a3
commit 3ca82d5df7
3 changed files with 32 additions and 23 deletions

View File

@ -753,7 +753,7 @@ static void add_child_status(int pid, int status) {
if (st->signal_fd)
scheme_signal_received_at(st->signal_fd);
if (st->unneeded)
(void)scheme_get_child_status(st->pid, 0, NULL);
(void)scheme_get_child_status(st->pid, 0, 0, NULL);
}
static int raw_get_child_status(int pid, int *status, int done_only, int do_remove, int do_free) {
@ -782,12 +782,12 @@ static int raw_get_child_status(int pid, int *status, int done_only, int do_remo
return found;
}
int scheme_get_child_status(int pid, int is_group, int *status) {
int scheme_get_child_status(int pid, int is_group, int can_check_group, int *status) {
int found = 0;
/* Check specific pid, in case the child has its own group
(either given by Racket or given to itself): */
{
if (can_check_group) {
pid_t pid2;
int status;

View File

@ -8528,6 +8528,30 @@ int scheme_os_pipe(intptr_t *a, int nearh)
/**************** Unix: signal stuff ******************/
#if defined(UNIX_PROCESSES)
void scheme_block_child_signals(int block)
XFORM_SKIP_PROC
{
#if defined(MZ_PLACES_WAITPID)
if (block)
scheme_wait_suspend();
else
scheme_wait_resume();
#else
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGCHLD);
# ifdef USE_ITIMER
sigaddset(&sigs, SIGPROF);
# endif
sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL);
#endif
}
#endif
#if defined(UNIX_PROCESSES) && !defined(MZ_PLACES_WAITPID)
#ifndef MZ_PRECISE_GC
@ -8541,21 +8565,6 @@ SHARED_OK static void *unused_pids;
static int need_to_check_children;
void scheme_block_child_signals(int block)
XFORM_SKIP_PROC
{
#if !defined(MZ_PLACES_WAITPID)
sigset_t sigs;
sigemptyset(&sigs);
sigaddset(&sigs, SIGCHLD);
# ifdef USE_ITIMER
sigaddset(&sigs, SIGPROF);
# endif
sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sigs, NULL);
#endif
}
static void child_done(int ingored)
XFORM_SKIP_PROC
{
@ -9012,7 +9021,7 @@ static int subp_done(Scheme_Object *so)
{
int status;
if (!sp->done) {
if (scheme_get_child_status(sp->pid, sp->is_group, &status)) {
if (scheme_get_child_status(sp->pid, sp->is_group, 1, &status)) {
sp->done = 1;
sp->status = status;
child_mref_done(sp);
@ -9078,7 +9087,7 @@ static Scheme_Object *subprocess_status(int argc, Scheme_Object **argv)
if (sp->done)
status = sp->status;
else {
if (!scheme_get_child_status(sp->pid, sp->is_group, &status)) {
if (!scheme_get_child_status(sp->pid, sp->is_group, 1, &status)) {
going = 1;
} else {
child_mref_done(sp);
@ -9167,9 +9176,9 @@ static Scheme_Object *do_subprocess_kill(Scheme_Object *_sp, Scheme_Object *kill
scheme_wait_suspend();
/* Don't pass sp->is_group, because we don't want to wait
/* Don't allow group checking, because we don't want to wait
on a group if we haven't already: */
if (scheme_get_child_status(sp->pid, 0, &status)) {
if (scheme_get_child_status(sp->pid, 0, 0, &status)) {
sp->status = status;
sp->done = 1;
child_mref_done(sp);

View File

@ -4047,7 +4047,7 @@ void scheme_spawn_master_place();
void scheme_places_block_child_signal();
void scheme_places_unblock_child_signal();
void scheme_places_start_child_signal_handler();
int scheme_get_child_status(int pid, int is_group, int *status);
int scheme_get_child_status(int pid, int is_group, int can_check_group, int *status);
int scheme_places_register_child(int pid, int is_group, void *signal_fd, int *status);
void scheme_wait_suspend();
void scheme_wait_resume();