diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | ext/pty/pty.c | 22 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | mjit.c | 51 | ||||
-rw-r--r-- | process.c | 287 | ||||
-rw-r--r-- | signal.c | 147 | ||||
-rw-r--r-- | spec/ruby/core/process/wait2_spec.rb | 38 | ||||
-rw-r--r-- | spec/ruby/core/process/wait_spec.rb | 126 | ||||
-rw-r--r-- | spec/ruby/core/process/waitall_spec.rb | 66 | ||||
-rw-r--r-- | test/ruby/test_optimization.rb | 2 | ||||
-rw-r--r-- | test/ruby/test_process.rb | 12 | ||||
-rw-r--r-- | test/ruby/test_rubyoptions.rb | 17 | ||||
-rw-r--r-- | thread.c | 34 | ||||
-rw-r--r-- | thread_pthread.c | 47 | ||||
-rw-r--r-- | vm_core.h | 20 | ||||
-rw-r--r-- | win32/Makefile.sub | 2 |
16 files changed, 238 insertions, 638 deletions
diff --git a/configure.ac b/configure.ac index 074a3fd394..b433863d64 100644 --- a/configure.ac +++ b/configure.ac @@ -766,7 +766,6 @@ AS_CASE(["$target_os"], AS_IF([test $gcc_major -lt 4 -o \( $gcc_major -eq 4 -a $gcc_minor -lt 3 \)], [ ac_cv_func___builtin_setjmp=no ]) - with_setjmp_type=sigsetjmp # to hijack SIGCHLD handler AC_CACHE_CHECK(for broken crypt with 8bit chars, rb_cv_broken_crypt, [AC_TRY_RUN([ #include <stdio.h> @@ -1783,7 +1782,6 @@ AC_CHECK_FUNCS(getsid) AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday AC_CHECK_FUNCS(getuidx) AC_CHECK_FUNCS(gmtime_r) -AC_CHECK_FUNCS(grantpt) AC_CHECK_FUNCS(initgroups) AC_CHECK_FUNCS(ioctl) AC_CHECK_FUNCS(isfinite) diff --git a/ext/pty/pty.c b/ext/pty/pty.c index 1ac89061c1..b3c7535321 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -246,13 +246,19 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, /* Unix98 PTY */ int masterfd = -1, slavefd = -1; char *slavedevice; + struct sigaction dfl, old; + + dfl.sa_handler = SIG_DFL; + dfl.sa_flags = 0; + sigemptyset(&dfl.sa_mask); #if defined(__sun) || (defined(__FreeBSD__) && __FreeBSD_version < 902000) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ /* FreeBSD 9.2 or later supports O_CLOEXEC * http://www.freebsd.org/cgi/query-pr.cgi?pr=162374 */ if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1) goto error; - if (rb_grantpt(masterfd) == -1) goto error; + if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; + if (grantpt(masterfd) == -1) goto grantpt_error; rb_fd_fix_cloexec(masterfd); #else { @@ -266,8 +272,10 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if ((masterfd = posix_openpt(flags)) == -1) goto error; } rb_fd_fix_cloexec(masterfd); - if (rb_grantpt(masterfd) == -1) goto error; + if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; + if (grantpt(masterfd) == -1) goto grantpt_error; #endif + if (sigaction(SIGCHLD, &old, NULL) == -1) goto error; if (unlockpt(masterfd) == -1) goto error; if ((slavedevice = ptsname(masterfd)) == NULL) goto error; if (no_mesg(slavedevice, nomesg) == -1) goto error; @@ -285,6 +293,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; + grantpt_error: + sigaction(SIGCHLD, &old, NULL); error: if (slavefd != -1) close(slavefd); if (masterfd != -1) close(masterfd); @@ -336,17 +346,21 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, extern char *ptsname(int); extern int unlockpt(int); + extern int grantpt(int); #if defined(__sun) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ if((masterfd = open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; - if(rb_grantpt(masterfd) == -1) goto error; + s = signal(SIGCHLD, SIG_DFL); + if(grantpt(masterfd) == -1) goto error; rb_fd_fix_cloexec(masterfd); #else if((masterfd = rb_cloexec_open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; rb_update_max_fd(masterfd); - if(rb_grantpt(masterfd) == -1) goto error; + s = signal(SIGCHLD, SIG_DFL); + if(grantpt(masterfd) == -1) goto error; #endif + signal(SIGCHLD, s); if(unlockpt(masterfd) == -1) goto error; if((slavedevice = ptsname(masterfd)) == NULL) goto error; if (no_mesg(slavedevice, nomesg) == -1) goto error; diff --git a/internal.h b/internal.h index b555bbab06..59e855c850 100644 --- a/internal.h +++ b/internal.h @@ -2042,9 +2042,6 @@ VALUE rb_gcd_normal(VALUE self, VALUE other); VALUE rb_gcd_gmp(VALUE x, VALUE y); #endif -/* signal.c (export) */ -int rb_grantpt(int fd); - /* string.c (export) */ #ifdef RUBY_ENCODING_H /* internal use */ @@ -80,7 +80,6 @@ #include "constant.h" #include "id_table.h" #include "ruby_assert.h" -#include "ruby/thread.h" #include "ruby/util.h" #include "ruby/version.h" @@ -119,10 +118,6 @@ extern void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lo extern int rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void)); -/* process.c */ -rb_pid_t ruby_waitpid_locked(rb_vm_t *, rb_pid_t, int *status, int options, - rb_nativethread_cond_t *cond); - #define RB_CONDATTR_CLOCK_MONOTONIC 1 #ifdef _WIN32 @@ -268,7 +263,7 @@ real_ms_time(void) static int sprint_uniq_filename(char *str, size_t size, unsigned long id, const char *prefix, const char *suffix) { - return snprintf(str, size, "%s/%sp%"PRI_PIDT_PREFIX"uu%lu%s", tmp_dir, prefix, getpid(), id, suffix); + return snprintf(str, size, "%s/%sp%luu%lu%s", tmp_dir, prefix, (unsigned long) getpid(), id, suffix); } /* Return an unique file name in /tmp with PREFIX and SUFFIX and @@ -406,42 +401,23 @@ start_process(const char *path, char *const *argv) static int exec_process(const char *path, char *const argv[]) { - int stat, exit_code = -2; + int stat, exit_code; pid_t pid; - rb_vm_t *vm = (RUBY_SIGCHLD || SIGCHLD_LOSSY) ? GET_VM() : 0; - rb_nativethread_cond_t cond; - - if (vm) { - rb_native_cond_initialize(&cond); - rb_native_mutex_lock(&vm->waitpid_lock); - } pid = start_process(path, argv); - for (;pid > 0;) { - pid_t r = vm ? ruby_waitpid_locked(vm, pid, &stat, 0, &cond) - : waitpid(pid, &stat, 0); - if (r == -1) { - if (errno == EINTR) continue; - fprintf(stderr, "[%"PRI_PIDT_PREFIX"d] waitpid(%"PRI_PIDT_PREFIX"d): %s (SIGCHLD=%d,%u)\n", - getpid(), pid, strerror(errno), - RUBY_SIGCHLD, SIGCHLD_LOSSY); + if (pid <= 0) + return -2; + + for (;;) { + waitpid(pid, &stat, 0); + if (WIFEXITED(stat)) { + exit_code = WEXITSTATUS(stat); + break; + } else if (WIFSIGNALED(stat)) { + exit_code = -1; break; - } - else if (r == pid) { - if (WIFEXITED(stat)) { - exit_code = WEXITSTATUS(stat); - break; - } else if (WIFSIGNALED(stat)) { - exit_code = -1; - break; - } } } - - if (vm) { - rb_native_mutex_unlock(&vm->waitpid_lock); - rb_native_cond_destroy(&cond); - } return exit_code; } @@ -1515,15 +1491,12 @@ mjit_init(struct mjit_options *opts) static void stop_worker(void) { - rb_execution_context_t *ec = GET_EC(); - stop_worker_p = TRUE; while (!worker_stopped) { verbose(3, "Sending cancel signal to worker"); CRITICAL_SECTION_START(3, "in stop_worker"); rb_native_cond_broadcast(&mjit_worker_wakeup); CRITICAL_SECTION_FINISH(3, "in stop_worker"); - RUBY_VM_CHECK_INTS(ec); } } @@ -885,6 +885,12 @@ pst_wcoredump(VALUE st) #endif } +struct waitpid_arg { + rb_pid_t pid; + int flags; + int *st; +}; + static rb_pid_t do_waitpid(rb_pid_t pid, int *st, int flags) { @@ -897,263 +903,45 @@ do_waitpid(rb_pid_t pid, int *st, int flags) #endif } -struct waitpid_state { - struct list_node wnode; - rb_execution_context_t *ec; - rb_nativethread_cond_t *cond; - rb_pid_t ret; - rb_pid_t pid; - int status; - int options; - int errnum; -}; - -void rb_native_mutex_lock(rb_nativethread_lock_t *); -void rb_native_mutex_unlock(rb_nativethread_lock_t *); -void rb_native_cond_signal(rb_nativethread_cond_t *); -void rb_native_cond_wait(rb_nativethread_cond_t *, rb_nativethread_lock_t *); -rb_nativethread_cond_t *rb_sleep_cond_get(const rb_execution_context_t *); -void rb_sleep_cond_put(rb_nativethread_cond_t *); - -static void -waitpid_notify(struct waitpid_state *w, rb_pid_t ret) -{ - w->ret = ret; - list_del_init(&w->wnode); - rb_native_cond_signal(w->cond); -} - -#ifdef _WIN32 /* for spawnvp result from mjit.c */ -# define waitpid_sys(pid,status,options) \ - (WaitForSingleObject((HANDLE)(pid), 0),\ - GetExitCodeProcess((HANDLE)(pid), (LPDWORD)(status))) -#else -# define waitpid_sys(pid,status,options) do_waitpid((pid),(status),(options)) -#endif - -/* called by timer thread */ -static void -waitpid_each(struct list_head *head) -{ - struct waitpid_state *w = 0, *next; - - list_for_each_safe(head, w, next, wnode) { - rb_pid_t ret; - - if (w->ec) - ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG); - else - ret = waitpid_sys(w->pid, &w->status, w->options | WNOHANG); - - if (!ret) continue; - if (ret == -1) w->errnum = errno; - - if (w->ec) { /* rb_waitpid */ - rb_thread_t *th = rb_ec_thread_ptr(w->ec); - - rb_native_mutex_lock(&th->interrupt_lock); - waitpid_notify(w, ret); - rb_native_mutex_unlock(&th->interrupt_lock); - } - else { /* ruby_waitpid_locked */ - waitpid_notify(w, ret); - } - } -} - -void -ruby_waitpid_all(rb_vm_t *vm) -{ - rb_native_mutex_lock(&vm->waitpid_lock); - waitpid_each(&vm->waiting_pids); - if (list_empty(&vm->waiting_pids)) { - waitpid_each(&vm->waiting_grps); - } - rb_native_mutex_unlock(&vm->waitpid_lock); -} - -static void -waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options) -{ - w->ret = 0; - w->pid = pid; - w->options = options; -} - -/* - * must be called with vm->waitpid_lock held, this is not interruptible - */ -rb_pid_t -ruby_waitpid_locked(rb_vm_t *vm, rb_pid_t pid, int *status, int options, - rb_nativethread_cond_t *cond) -{ - struct waitpid_state w; - - assert(!ruby_thread_has_gvl_p() && "must not have GVL"); - - waitpid_state_init(&w, pid, options); - if (w.pid > 0 || list_empty(&vm->waiting_pids)) - w.ret = do_waitpid(w.pid, &w.status, w.options | WNOHANG); - if (w.ret) { - if (w.ret == -1) w.errnum = errno; - } - else { - w.cond = cond; - w.ec = 0; - list_add(w.pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w.wnode); - do { - rb_native_cond_wait(w.cond, &vm->waitpid_lock); - } while (!w.ret); - list_del(&w.wnode); - } - if (status) { - *status = w.status; - } - if (w.ret == -1) errno = w.errnum; - return w.ret; -} - -static void -waitpid_wake(void *x) -{ - struct waitpid_state *w = x; - - /* th->interrupt_lock is already held by rb_threadptr_interrupt_common */ - rb_native_cond_signal(w->cond); -} - static void * -waitpid_nogvl(void *x) +rb_waitpid_blocking(void *data) { - struct waitpid_state *w = x; - rb_thread_t *th = rb_ec_thread_ptr(w->ec); - - rb_native_mutex_lock(&th->interrupt_lock); - /* - * We must check again before waiting, timer-thread may change w->ret - * by the time we enter this. And we may also be interrupted. - */ - if (!w->ret && !RUBY_VM_INTERRUPTED_ANY(w->ec)) { - if (SIGCHLD_LOSSY) { - rb_thread_wakeup_timer_thread(); - } - rb_native_cond_wait(w->cond, &th->interrupt_lock); - } - rb_native_mutex_unlock(&th->interrupt_lock); - - return 0; + struct waitpid_arg *arg = data; + rb_pid_t result = do_waitpid(arg->pid, arg->st, arg->flags); + return (void *)(VALUE)result; } -static VALUE -waitpid_sleep(VALUE x) -{ - struct waitpid_state *w = (struct waitpid_state *)x; - - while (!w->ret) { - rb_thread_call_without_gvl(waitpid_nogvl, w, waitpid_wake, w); - } - - return Qfalse; -} - -static VALUE -waitpid_cleanup(VALUE x) -{ - struct waitpid_state *w = (struct waitpid_state *)x; - - if (w->ret == 0) { - rb_vm_t *vm = rb_ec_vm_ptr(w->ec); - - rb_native_mutex_lock(&vm->waitpid_lock); - list_del(&w->wnode); - rb_native_mutex_unlock(&vm->waitpid_lock); - } - rb_sleep_cond_put(w->cond); - - return Qfalse; -} - -static void -waitpid_wait(struct waitpid_state *w) -{ - rb_vm_t *vm = rb_ec_vm_ptr(w->ec); - - /* - * Lock here to prevent do_waitpid from stealing work from the - * ruby_waitpid_locked done by mjit workers since mjit works - * outside of GVL - */ - rb_native_mutex_lock(&vm->waitpid_lock); - - if (w->pid > 0 || list_empty(&vm->waiting_pids)) - w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG); - if (w->ret) { - w->cond = 0; - if (w->ret == -1) w->errnum = errno; - } - else if (w->options & WNOHANG) { - w->cond = 0; - } - else { - w->cond = rb_sleep_cond_get(w->ec); - /* order matters, favor specified PIDs rather than -1 or 0 */ - list_add(w->pid > 0 ? &vm->waiting_pids : &vm->waiting_grps, &w->wnode); - } - - rb_native_mutex_unlock(&vm->waitpid_lock); - - if (w->cond) { - rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w); - } -} - -static void * -waitpid_blocking_no_SIGCHLD(void *x) -{ - struct waitpid_state *w = x; - - w->ret = do_waitpid(w->pid, &w->status, w->options); - - return 0; -} - -static void -waitpid_no_SIGCHLD(struct waitpid_state *w) +static rb_pid_t +do_waitpid_nonblocking(rb_pid_t pid, int *st, int flags) { - if (w->options & WNOHANG) { - w->ret = do_waitpid(w->pid, &w->status, w->options); - } - else { - do { - rb_thread_call_without_gvl(waitpid_blocking_no_SIGCHLD, w, - RUBY_UBF_PROCESS, 0); - } while (w->ret < 0 && errno == EINTR && (RUBY_VM_CHECK_INTS(w->ec),1)); - } - if (w->ret == -1) - w->errnum = errno; + void *result; + struct waitpid_arg arg; + arg.pid = pid; + arg.st = st; + arg.flags = flags; + result = rb_thread_call_without_gvl(rb_waitpid_blocking, &arg, + RUBY_UBF_PROCESS, 0); + return (rb_pid_t)(VALUE)result; } rb_pid_t rb_waitpid(rb_pid_t pid, int *st, int flags) { - struct waitpid_state w; + rb_pid_t result; - waitpid_state_init(&w, pid, flags); - w.ec = GET_EC(); - - if (RUBY_SIGCHLD || SIGCHLD_LOSSY) { - waitpid_wait(&w); + if (flags & WNOHANG) { + result = do_waitpid(pid, st, flags); } else { - waitpid_no_SIGCHLD(&w); + while ((result = do_waitpid_nonblocking(pid, st, flags)) < 0 && + (errno == EINTR)) { + RUBY_VM_CHECK_INTS(GET_EC()); + } } - - if (st) *st = w.status; - if (w.ret > 0) { - rb_last_status_set(w.status, w.ret); + if (result > 0) { + rb_last_status_set(*st, result); } - if (w.ret == -1) errno = w.errnum; - return w.ret; + return result; } @@ -3807,8 +3595,6 @@ disable_child_handler_fork_child(struct child_handler_disabler_state *old, char } } - /* non-Ruby child process, ensure cmake can see SIGCHLD */ - sigemptyset(&old->sigmask); ret = sigprocmask(SIG_SETMASK, &old->sigmask, NULL); /* async-signal-safe */ if (ret != 0) { ERRMSG("sigprocmask"); @@ -4300,6 +4086,16 @@ rb_f_system(int argc, VALUE *argv) VALUE execarg_obj; struct rb_execarg *eargp; +#if defined(SIGCLD) && !defined(SIGCHLD) +# define SIGCHLD SIGCLD +#endif + +#ifdef SIGCHLD + RETSIGTYPE (*chfunc)(int); + + rb_last_status_clear(); + chfunc = signal(SIGCHLD, SIG_DFL); +#endif execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE); pid = rb_execarg_spawn(execarg_obj, NULL, 0); #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) @@ -4310,6 +4106,9 @@ rb_f_system(int argc, VALUE *argv) rb_sys_fail("Another thread waited the process started by system()."); } #endif +#ifdef SIGCHLD + signal(SIGCHLD, chfunc); +#endif TypedData_Get_Struct(execarg_obj, struct rb_execarg, &exec_arg_data_type, eargp); if (pid < 0) { if (eargp->exception) { @@ -62,11 +62,12 @@ ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp, } #endif -#define FOREACH_SIGNAL(sig, offset) \ - for (sig = siglist + (offset); sig < siglist + numberof(siglist); ++sig) -enum { LONGEST_SIGNAME = 7 }; /* MIGRATE and RETRACT */ +#ifndef NSIG +# define NSIG (_SIGMAX + 1) /* For QNX */ +#endif + static const struct signals { - char signm[LONGEST_SIGNAME + 1]; + const char *signm; int signo; } siglist [] = { {"EXIT", 0}, @@ -128,9 +129,15 @@ static const struct signals { #ifdef SIGCONT {"CONT", SIGCONT}, #endif -#if RUBY_SIGCHLD - {"CHLD", RUBY_SIGCHLD }, - {"CLD", RUBY_SIGCHLD }, +#ifdef SIGCHLD + {"CHLD", SIGCHLD}, +#endif +#ifdef SIGCLD + {"CLD", SIGCLD}, +#else +# ifdef SIGCHLD + {"CLD", SIGCHLD}, +# endif #endif #ifdef SIGTTIN {"TTIN", SIGTTIN}, @@ -195,6 +202,7 @@ static const struct signals { #ifdef SIGINFO {"INFO", SIGINFO}, #endif + {NULL, 0} }; static const char signame_prefix[3] = "SIG"; @@ -206,7 +214,7 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr) const struct signals *sigs; VALUE vsig = *sig_ptr; const char *nm; - long len, nmlen; + long len; int prefix = 0; if (RB_SYMBOL_P(vsig)) { @@ -260,12 +268,9 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr) } if (prefix_ptr) *prefix_ptr = prefix; - nmlen = len - prefix; - nm += prefix; - if (nmlen > LONGEST_SIGNAME) goto unsupported; - FOREACH_SIGNAL(sigs, !exit) { - if (memcmp(sigs->signm, nm, nmlen) == 0 && - sigs->signm[nmlen] == '\0') { + for (sigs = siglist + !exit; sigs->signm; sigs++) { + if (memcmp(sigs->signm, nm + prefix, len - prefix) == 0 && + sigs->signm[len - prefix] == '\0') { return negative ? -sigs->signo : sigs->signo; } } @@ -277,10 +282,9 @@ signo2signm(int no) { const struct signals *sigs; - FOREACH_SIGNAL(sigs, 0) { + for (sigs = siglist; sigs->signm; sigs++) if (sigs->signo == no) return sigs->signm; - } return 0; } @@ -698,29 +702,12 @@ signal_enque(int sig) ATOMIC_INC(signal_buff.size); } -static rb_atomic_t sigchld_hit; - -/* Prevent compiler from reordering access */ -#define ACCESS_ONCE(type,x) (*((volatile type *)&(x))) - static RETSIGTYPE sighandler(int sig) { int old_errnum = errno; - /* the VM always needs to handle SIGCHLD for rb_waitpid */ - if (sig == RUBY_SIGCHLD) { - rb_vm_t *vm = GET_VM(); - ATOMIC_EXCHANGE(sigchld_hit, 1); - - /* avoid spurious wakeup in main thread iff nobody uses trap(:CHLD) */ - if (vm && ACCESS_ONCE(VALUE, vm->trap_list.cmd[sig])) { - signal_enque(sig); - } - } - else { - signal_enque(sig); - } + signal_enque(sig); rb_thread_wakeup_timer_thread(); #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) ruby_signal(sig, sighandler); @@ -755,7 +742,6 @@ rb_enable_interrupt(void) #ifdef HAVE_PTHREAD_SIGMASK sigset_t mask; sigemptyset(&mask); - sigaddset(&mask, RUBY_SIGCHLD); /* timer-thread handles this */ pthread_sigmask(SIG_SETMASK, &mask, NULL); #endif } @@ -1066,17 +1052,6 @@ rb_trap_exit(void) } } -void ruby_waitpid_all(rb_vm_t *); /* process.c */ - -/* only runs in the timer-thread */ -void -ruby_sigchld_handler(rb_vm_t *vm) -{ - if (SIGCHLD_LOSSY || ATOMIC_EXCHANGE(sigchld_hit, 0)) { - ruby_waitpid_all(vm); - } -} - void rb_signal_exec(rb_thread_t *th, int sig) { @@ -1143,9 +1118,6 @@ default_handler(int sig) #ifdef SIGUSR2 case SIGUSR2: #endif -#if RUBY_SIGCHLD - case RUBY_SIGCHLD: -#endif func = sighandler; break; #ifdef SIGBUS @@ -1183,9 +1155,6 @@ trap_handler(VALUE *cmd, int sig) VALUE command; if (NIL_P(*cmd)) { - if (sig == RUBY_SIGCHLD) { - goto sig_dfl; - } func = SIG_IGN; } else { @@ -1206,9 +1175,6 @@ trap_handler(VALUE *cmd, int sig) break; case 14: if (memcmp(cptr, "SYSTEM_DEFAULT", 14) == 0) { - if (sig == RUBY_SIGCHLD) { - goto sig_dfl; - } func = SIG_DFL; *cmd = 0; } @@ -1216,9 +1182,6 @@ trap_handler(VALUE *cmd, int sig) case 7: if (memcmp(cptr, "SIG_IGN", 7) == 0) { sig_ign: - if (sig == RUBY_SIGCHLD) { - goto sig_dfl; - } func = SIG_IGN; *cmd = Qtrue; } @@ -1305,7 +1268,7 @@ trap(int sig, sighandler_t func, VALUE command) break; } - ACCESS_ONCE(VALUE, vm->trap_list.cmd[sig]) = command; + vm->trap_list.cmd[sig] = command; vm->trap_list.safe[sig] = rb_safe_level(); return oldcmd; @@ -1421,7 +1384,7 @@ sig_list(void) VALUE h = rb_hash_new(); const struct signals *sigs; - FOREACH_SIGNAL(sigs, 0) { + for (sigs = siglist; sigs->signm; sigs++) { rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo)); } return h; @@ -1450,18 +1413,20 @@ install_sighandler(int signum, sighandler_t handler) # define install_sighandler(signum, handler) \ INSTALL_SIGHANDLER(install_sighandler(signum, handler), #signum, signum) -#if RUBY_SIGCHLD +#if defined(SIGCLD) || defined(SIGCHLD) static int init_sigchld(int sig) { sighandler_t oldfunc; - sighandler_t func = sighandler; oldfunc = ruby_signal(sig, SIG_DFL); if (oldfunc == SIG_ERR) return -1; - ruby_signal(sig, func); - ACCESS_ONCE(VALUE, GET_VM()->trap_list.cmd[sig]) = 0; - + if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) { + ruby_signal(sig, oldfunc); + } + else { + GET_VM()->trap_list.cmd[sig] = 0; + } return 0; } @@ -1577,55 +1542,11 @@ Init_signal(void) install_sighandler(SIGSYS, sig_do_nothing); #endif -#if RUBY_SIGCHLD - init_sigchld(RUBY_SIGCHLD); +#if defined(SIGCLD) + init_sigchld(SIGCLD); +#elif defined(SIGCHLD) + init_sigchld(SIGCHLD); #endif rb_enable_interrupt(); } - -#if defined(HAVE_GRANTPT) -extern int grantpt(int); -#else -static int -fake_grantfd(int masterfd) -{ - errno = ENOSYS; - return -1; -} -#define grantpt(fd) fake_grantfd(fd) -#endif - -int -rb_grantpt(int masterfd) -{ - if (RUBY_SIGCHLD) { - rb_vm_t *vm = GET_VM(); - int ret, e; - - /* - * Prevent waitpid calls from Ruby by taking waitpid_lock. - * Pedantically, grantpt(3) is undefined if a non-default - * SIGCHLD handler is defined, but preventing conflicting - * waitpid calls ought to be sufficient. - * - * We could install the default sighandler temporarily, but that - * could cause SIGCHLD to be missed by other threads. Blocking - * SIGCHLD won't work here, either, unless we stop and restart - * timer-thread (as only timer-thread sees SIGCHLD), but that - * seems like overkill. - */ - rb_nativethread_lock_lock(&vm->waitpid_lock); - { - ret = grantpt(masterfd); /* may spawn `pt_chown' and wait on it */ - if (ret < 0) e = errno; - } - rb_nativethread_lock_unlock(&vm->waitpid_lock); - - if (ret < 0) errno = e; - return ret; - } - else { - return grantpt(masterfd); - } -} diff --git a/spec/ruby/core/process/wait2_spec.rb b/spec/ruby/core/process/wait2_spec.rb index d0163f80af..3f5aa3c7e2 100644 --- a/spec/ruby/core/process/wait2_spec.rb +++ b/spec/ruby/core/process/wait2_spec.rb @@ -4,37 +4,31 @@ describe "Process.wait2" do before :all do # HACK: this kludge is temporarily necessary because some # misbehaving spec somewhere else does not clear processes - # Note: background processes are unavoidable with MJIT, - # but we shouldn't reap them from Ruby-space begin Process.wait(-1, Process::WNOHANG) - without_feature :mjit do - $stderr.puts "Leaked process before wait2 specs! Waiting for it" - end + $stderr.puts "Leaked process before wait2 specs! Waiting for it" leaked = Process.waitall - $stderr.puts "leaked before wait2 specs: #{leaked}" unless leaked.empty? - with_feature :mjit do - # Ruby-space should not see PIDs used by mjit - leaked.should be_empty - end + $stderr.puts "leaked before wait2 specs: #{leaked}" rescue Errno::ECHILD # No child processes rescue NotImplementedError end end - platform_is_not :windows do - it "returns the pid and status of child process" do - pidf = Process.fork { Process.exit! 99 } - results = Process.wait2 - results.size.should == 2 - pidw, status = results - pidf.should == pidw - status.exitstatus.should == 99 + without_feature :mjit do # [Bug #14867] + platform_is_not :windows do + it "returns the pid and status of child process" do + pidf = Process.fork { Process.exit! 99 } + results = Process.wait2 + results.size.should == 2 + pidw, status = results + pidf.should == pidw + status.exitstatus.should == 99 + end end - end - it "raises a StandardError if no child processes exist" do - lambda { Process.wait2 }.should raise_error(Errno::ECHILD) - lambda { Process.wait2 }.should raise_error(StandardError) + it "raises a StandardError if no child processes exist" do + lambda { Process.wait2 }.should raise_error(Errno::ECHILD) + lambda { Process.wait2 }.should raise_error(StandardError) + end end end diff --git a/spec/ruby/core/process/wait_spec.rb b/spec/ruby/core/process/wait_spec.rb index 5130bb4391..447c62f42a 100644 --- a/spec/ruby/core/process/wait_spec.rb +++ b/spec/ruby/core/process/wait_spec.rb @@ -8,87 +8,85 @@ describe "Process.wait" do begin leaked = Process.waitall puts "leaked before wait specs: #{leaked}" unless leaked.empty? - with_feature :mjit do - # Ruby-space should not see PIDs used by mjit - leaked.should be_empty - end rescue NotImplementedError end end - it "raises an Errno::ECHILD if there are no child processes" do - lambda { Process.wait }.should raise_error(Errno::ECHILD) - end - - platform_is_not :windows do - it "returns its childs pid" do - pid = Process.spawn(ruby_cmd('exit')) - Process.wait.should == pid + without_feature :mjit do # [Bug #14867] + it "raises an Errno::ECHILD if there are no child processes" do + lambda { Process.wait }.should raise_error(Errno::ECHILD) end - it "sets $? to a Process::Status" do - pid = Process.spawn(ruby_cmd('exit')) - Process.wait - $?.should be_kind_of(Process::Status) - $?.pid.should == pid - end + platform_is_not :windows do + it "returns its childs pid" do + pid = Process.spawn(ruby_cmd('exit')) + Process.wait.should == pid + end - it "waits for any child process if no pid is given" do - pid = Process.spawn(ruby_cmd('exit')) - Process.wait.should == pid - lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) - end + it "sets $? to a Process::Status" do + pid = Process.spawn(ruby_cmd('exit')) + Process.wait + $?.should be_kind_of(Process::Status) + $?.pid.should == pid + end - it "waits for a specific child if a pid is given" do - pid1 = Process.spawn(ruby_cmd('exit')) - pid2 = Process.spawn(ruby_cmd('exit')) - Process.wait(pid2).should == pid2 - Process.wait(pid1).should == pid1 - lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) - lambda { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH) - end + it "waits for any child process if no pid is given" do + pid = Process.spawn(ruby_cmd('exit')) + Process.wait.should == pid + lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + end - it "coerces the pid to an Integer" do - pid1 = Process.spawn(ruby_cmd('exit')) - Process.wait(mock_int(pid1)).should == pid1 - lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) - end + it "waits for a specific child if a pid is given" do + pid1 = Process.spawn(ruby_cmd('exit')) + pid2 = Process.spawn(ruby_cmd('exit')) + Process.wait(pid2).should == pid2 + Process.wait(pid1).should == pid1 + lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) + lambda { Process.kill(0, pid2) }.should raise_error(Errno::ESRCH) + end - # This spec is probably system-dependent. - it "waits for a child whose process group ID is that of the calling process" do - pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true) - pid2 = Process.spawn(ruby_cmd('exit')) + it "coerces the pid to an Integer" do + pid1 = Process.spawn(ruby_cmd('exit')) + Process.wait(mock_int(pid1)).should == pid1 + lambda { Process.kill(0, pid1) }.should raise_error(Errno::ESRCH) + end - Process.wait(0).should == pid2 - Process.wait.should == pid1 - end + # This spec is probably system-dependent. + it "waits for a child whose process group ID is that of the calling process" do + pid1 = Process.spawn(ruby_cmd('exit'), pgroup: true) + pid2 = Process.spawn(ruby_cmd('exit')) - # This spec is probably system-dependent. - it "doesn't block if no child is available when WNOHANG is used" do - read, write = IO.pipe - pid = Process.fork do - read.close - Signal.trap("TERM") { Process.exit! } - write << 1 - write.close - sleep + Process.wait(0).should == pid2 + Process.wait.should == pid1 end - Process.wait(pid, Process::WNOHANG).should be_nil + # This spec is probably system-dependent. + it "doesn't block if no child is available when WNOHANG is used" do + read, write = IO.pipe + pid = Process.fork do + read.close + Signal.trap("TERM") { Process.exit! } + write << 1 + write.close + sleep + end - # wait for the child to setup its TERM handler - write.close - read.read(1) - read.close + Process.wait(pid, Process::WNOHANG).should be_nil - Process.kill("TERM", pid) - Process.wait.should == pid - end + # wait for the child to setup its TERM handler + write.close + read.read(1) + read.close - it "always accepts flags=0" do - pid = Process.spawn(ruby_cmd('exit')) - Process.wait(-1, 0).should == pid - lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + Process.kill("TERM", pid) + Process.wait.should == pid + end + + it "always accepts flags=0" do + pid = Process.spawn(ruby_cmd('exit')) + Process.wait(-1, 0).should == pid + lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + end end end end diff --git a/spec/ruby/core/process/waitall_spec.rb b/spec/ruby/core/process/waitall_spec.rb index bdc1ea7490..ff06ae21f9 100644 --- a/spec/ruby/core/process/waitall_spec.rb +++ b/spec/ruby/core/process/waitall_spec.rb @@ -8,41 +8,43 @@ describe "Process.waitall" do end end - it "returns an empty array when there are no children" do - Process.waitall.should == [] - end - - it "takes no arguments" do - lambda { Process.waitall(0) }.should raise_error(ArgumentError) - end + without_feature :mjit do # [Bug #14867] + it "returns an empty array when there are no children" do + Process.waitall.should == [] + end - platform_is_not :windows do - it "waits for all children" do - pids = [] - pids << Process.fork { Process.exit! 2 } - pids << Process.fork { Process.exit! 1 } - pids << Process.fork { Process.exit! 0 } - Process.waitall - pids.each { |pid| - lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) - } + it "takes no arguments" do + lambda { Process.waitall(0) }.should raise_error(ArgumentError) end - it "returns an array of pid/status pairs" do - pids = [] - pids << Process.fork { Process.exit! 2 } - pids << Process.fork { Process.exit! 1 } - pids << Process.fork { Process.exit! 0 } - a = Process.waitall - a.should be_kind_of(Array) - a.size.should == 3 - pids.each { |pid| - pid_status = a.assoc(pid) - pid_status.should be_kind_of(Array) - pid_status.size.should == 2 - pid_status.first.should == pid - pid_status.last.should be_kind_of(Process::Status) - } + platform_is_not :windows do + it "waits for all children" do + pids = [] + pids << Process.fork { Process.exit! 2 } + pids << Process.fork { Process.exit! 1 } + pids << Process.fork { Process.exit! 0 } + Process.waitall + pids.each { |pid| + lambda { Process.kill(0, pid) }.should raise_error(Errno::ESRCH) + } + end + + it "returns an array of pid/status pairs" do + pids = [] + pids << Process.fork { Process.exit! 2 } + pids << Process.fork { Process.exit! 1 } + pids << Process.fork { Process.exit! 0 } + a = Process.waitall + a.should be_kind_of(Array) + a.size.should == 3 + pids.each { |pid| + pid_status = a.assoc(pid) + pid_status.should be_kind_of(Array) + pid_status.size.should == 2 + pid_status.first.should == pid + pid_status.last.should be_kind_of(Process::Status) + } + end end end end diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 32bdcef13d..6bfaf11d7f 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -707,7 +707,7 @@ class TestRubyOptimization < Test::Unit::TestCase end def test_clear_unreachable_keyword_args - assert_separately [], <<-END, timeout: 30 + assert_separately [], <<-END, timeout: 20 script = <<-EOS if true else diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 6a32702b03..36ae94908a 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1426,6 +1426,7 @@ class TestProcess < Test::Unit::TestCase end def test_wait_without_arg + skip "[Bug #14867]" if RubyVM::MJIT.enabled? with_tmpchdir do write_file("foo", "sleep 0.1") pid = spawn(RUBY, "foo") @@ -1434,6 +1435,7 @@ class TestProcess < Test::Unit::TestCase end def test_wait2 + skip "[Bug #14867]" if RubyVM::MJIT.enabled? with_tmpchdir do write_file("foo", "sleep 0.1") pid = spawn(RUBY, "foo") @@ -1442,6 +1444,7 @@ class TestProcess < Test::Unit::TestCase end def test_waitall + skip "[Bug #14867]" if RubyVM::MJIT.enabled? with_tmpchdir do write_file("foo", "sleep 0.1") ps = (0...3).map { spawn(RUBY, "foo") }.sort @@ -1456,9 +1459,7 @@ class TestProcess < Test::Unit::TestCase def test_wait_exception bug11340 = '[ruby-dev:49176] [Bug #11340]' t0 = t1 = nil - sec = 3 - code = "puts;STDOUT.flush;Thread.start{gets;exit};sleep(#{sec})" - IO.popen([RUBY, '-e', code], 'r+') do |f| + IO.popen([RUBY, '-e', 'puts;STDOUT.flush;Thread.start{gets;exit};sleep(3)'], 'r+') do |f| pid = f.pid f.gets t0 = Time.now @@ -1472,11 +1473,10 @@ class TestProcess < Test::Unit::TestCase th.kill.join end t1 = Time.now - diff = t1 - t0 - assert_operator(diff, :<, sec, - ->{"#{bug11340}: #{diff} seconds to interrupt Process.wait"}) f.puts end + assert_operator(t1 - t0, :<, 3, + ->{"#{bug11340}: #{t1-t0} seconds to interrupt Process.wait"}) end def test_abort diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index edd44ca0ae..d67cdcb984 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -1,7 +1,6 @@ # -*- coding: us-ascii -*- require 'test/unit' -require 'timeout' require 'tmpdir' require 'tempfile' require_relative '../lib/jit_support' @@ -591,18 +590,14 @@ class TestRubyOptions < Test::Unit::TestCase pid = spawn(EnvUtil.rubybin, "test-script") ps = nil - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - stop = now + 30 begin sleep 0.1 ps = `#{PSCMD.join(' ')} #{pid}` break if /hello world/ =~ ps - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - end until Process.wait(pid, Process::WNOHANG) || now > stop + end until Process.wait(pid, Process::WNOHANG) assert_match(/hello world/, ps) - assert_operator now, :<, stop Process.kill :KILL, pid - Timeout.timeout(5) { Process.wait(pid) } + Process.wait(pid) end end @@ -621,18 +616,14 @@ class TestRubyOptions < Test::Unit::TestCase pid = spawn(EnvUtil.rubybin, "test-script") ps = nil - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - stop = now + 30 begin sleep 0.1 ps = `#{PSCMD.join(' ')} #{pid}` break if /hello world/ =~ ps - now = Process.clock_gettime(Process::CLOCK_MONOTONIC) - end until Process.wait(pid, Process::WNOHANG) || now > stop + end until Process.wait(pid, Process::WNOHANG) assert_match(/hello world/, ps) - assert_operator now, :<, stop Process.kill :KILL, pid - Timeout.timeout(5) { Process.wait(pid) } + Process.wait(pid) end end @@ -413,10 +413,6 @@ rb_vm_gvl_destroy(rb_vm_t *vm) gvl_release(vm); gvl_destroy(vm); rb_native_mutex_destroy(&vm->thread_destruct_lock); - if (0) { - /* may be held by running threads */ - rb_native_mutex_destroy(&vm->waitpid_lock); - } } void @@ -4135,9 +4131,6 @@ rb_gc_set_stack_end(VALUE **stack_end_p) #endif -/* signal.c */ -void ruby_sigchld_handler(rb_vm_t *); - /* * */ @@ -4170,7 +4163,6 @@ timer_thread_function(void *arg) rb_native_mutex_unlock(&vm->thread_destruct_lock); /* check signal */ - ruby_sigchld_handler(vm); rb_threadptr_check_signal(vm->main_thread); #if 0 @@ -4255,9 +4247,6 @@ rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const r } rb_vm_living_threads_init(vm); rb_vm_living_threads_insert(vm, th); - - /* may be held by MJIT threads in parent */ - rb_native_mutex_initialize(&vm->waitpid_lock); vm->fork_gen++; vm->sleeper = 0; @@ -5010,7 +4999,6 @@ Init_Thread(void) gvl_init(th->vm); gvl_acquire(th->vm, th); rb_native_mutex_initialize(&th->vm->thread_destruct_lock); - rb_native_mutex_initialize(&th->vm->waitpid_lock); rb_native_mutex_initialize(&th->interrupt_lock); th->pending_interrupt_queue = rb_ary_tmp_new(0); @@ -5314,25 +5302,3 @@ rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data) return rb_ensure(b_proc, data, rb_ary_pop, cur_th->pending_interrupt_mask_stack); } - -#ifndef USE_NATIVE_SLEEP_COND -# define USE_NATIVE_SLEEP_COND (0) -#endif - -#if !USE_NATIVE_SLEEP_COND -rb_nativethread_cond_t * -rb_sleep_cond_get(const rb_execution_context_t *ec) -{ - rb_nativethread_cond_t *cond = ALLOC(rb_nativethread_cond_t); - rb_native_cond_initialize(cond); - - return cond; -} - -void -rb_sleep_cond_put(rb_nativethread_cond_t *cond) -{ - rb_native_cond_destroy(cond); - xfree(cond); -} -#endif /* !USE_NATIVE_SLEEP_COND */ diff --git a/thread_pthread.c b/thread_pthread.c index 722ce44487..8a4825548b 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1369,7 +1369,7 @@ setup_communication_pipe(void) * @pre the calling context is in the timer thread. */ static inline void -timer_thread_sleep(rb_vm_t *vm) +timer_thread_sleep(rb_global_vm_lock_t* gvl) { int result; int need_polling; @@ -1382,15 +1382,7 @@ timer_thread_sleep(rb_vm_t *vm) need_polling = !ubf_threads_empty(); - if (SIGCHLD_LOSSY && !need_polling) { - rb_native_mutex_lock(&vm->waitpid_lock); - if (!list_empty(&vm->waiting_pids) || !list_empty(&vm->waiting_grps)) { - need_polling = 1; - } - rb_native_mutex_unlock(&vm->waitpid_lock); - } - - if (vm->gvl.waiting > 0 || need_polling) { + if (gvl->waiting > 0 || need_polling) { /* polling (TIME_QUANTUM_USEC usec) */ result = poll(pollfds, 1, TIME_QUANTUM_USEC/1000); } @@ -1429,7 +1421,7 @@ static rb_nativethread_lock_t timer_thread_lock; static rb_nativethread_cond_t timer_thread_cond; static inline void -timer_thread_sleep(rb_vm_t *unused) +timer_thread_sleep(rb_global_vm_lock_t* unused) { struct timespec ts; ts.tv_sec = 0; @@ -1493,14 +1485,7 @@ native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name) static void * thread_timer(void *p) { - rb_vm_t *vm = p; -#ifdef HAVE_PTHREAD_SIGMASK /* mainly to enable SIGCHLD */ - { - sigset_t mask; - sigemptyset(&mask); - pthread_sigmask(SIG_SETMASK, &mask, NULL); - } -#endif + rb_global_vm_lock_t *gvl = (rb_global_vm_lock_t *)p; if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n"); @@ -1522,7 +1507,7 @@ thread_timer(void *p) if (TT_DEBUG) WRITE_CONST(2, "tick\n"); /* wait */ - timer_thread_sleep(vm); + timer_thread_sleep(gvl); } #if USE_SLEEPY_TIMER_THREAD CLOSE_INVALIDATE(normal[0]); @@ -1594,7 +1579,7 @@ rb_thread_create_timer_thread(void) if (timer_thread.created) { rb_bug("rb_thread_create_timer_thread: Timer thread was already created\n"); } - err = pthread_create(&timer_thread.id, &attr, thread_timer, vm); + err = pthread_create(&timer_thread.id, &attr, thread_timer, &vm->gvl); pthread_attr_destroy(&attr); if (err == EINVAL) { @@ -1605,7 +1590,7 @@ rb_thread_create_timer_thread(void) * default stack size is enough for them: */ stack_size = 0; - err = pthread_create(&timer_thread.id, NULL, thread_timer, vm); + err = pthread_create(&timer_thread.id, NULL, thread_timer, &vm->gvl); } if (err != 0) { rb_warn("pthread_create failed for timer: %s, scheduling broken", @@ -1786,22 +1771,4 @@ rb_thread_create_mjit_thread(void (*child_hook)(void), void (*worker_func)(void) return ret; } -#define USE_NATIVE_SLEEP_COND (1) - -#if USE_NATIVE_SLEEP_COND -rb_nativethread_cond_t * -rb_sleep_cond_get(const rb_execution_context_t *ec) -{ - rb_thread_t *th = rb_ec_thread_ptr(ec); - - return &th->native_thread_data.sleep_cond; -} - -void -rb_sleep_cond_put(rb_nativethread_cond_t *cond) -{ - /* no-op */ -} -#endif /* USE_NATIVE_SLEEP_COND */ - #endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */ @@ -92,21 +92,6 @@ #define RUBY_NSIG NSIG -#if defined(SIGCLD) -# define RUBY_SIGCHLD (SIGCLD) -#elif defined(SIGCHLD) -# define RUBY_SIGCHLD (SIGCHLD) -#else -# define RUBY_SIGCHLD (0) -#endif - -/* platforms with broken or non-existent SIGCHLD work by polling */ -#if defined(__APPLE__) || defined(__WIN32__) || defined(_WIN32) -# define SIGCHLD_LOSSY (1) -#else -# define SIGCHLD_LOSSY (0) -#endif - #ifdef HAVE_STDARG_PROTOTYPES #include <stdarg.h> #define va_init_list(a,b) va_start((a),(b)) @@ -568,9 +553,6 @@ typedef struct rb_vm_struct { #endif rb_serial_t fork_gen; - rb_nativethread_lock_t waitpid_lock; - struct list_head waiting_pids; /* PID > 0: <=> struct waitpid_state */ - struct list_head waiting_grps; /* PID <= 0: <=> struct waitpid_state */ struct list_head waiting_fds; /* <=> struct waiting_fd */ struct list_head living_threads; VALUE thgroup_default; @@ -1579,8 +1561,6 @@ static inline void rb_vm_living_threads_init(rb_vm_t *vm) { list_head_init(&vm->waiting_fds); - list_head_init(&vm->waiting_pids); - list_head_init(&vm->waiting_grps); list_head_init(&vm->living_threads); vm->living_thread_num = 0; } diff --git a/win32/Makefile.sub b/win32/Makefile.sub index fd852c21b7..20b47a581a 100644 --- a/win32/Makefile.sub +++ b/win32/Makefile.sub @@ -760,7 +760,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub #define ssize_t int !endif #define PRI_LL_PREFIX "I64" -#define PRI_PIDT_PREFIX "I" +#define PRI_PIDT_PREFIX PRI_INT_PREFIX #define GETGROUPS_T int #define RETSIGTYPE void #define TYPEOF_TIMEVAL_TV_SEC long |