From fbee3b8f75a881072fadb215dd1133e9a5cee30f Mon Sep 17 00:00:00 2001 From: normal Date: Tue, 30 Oct 2018 01:12:38 +0000 Subject: revert r65434 http://mswinci.japaneast.cloudapp.azure.com/vc12-x64/ruby-trunk/log/20181030T003541Z.fail.html.gz I have no chance of getting anything to work on proprietary platforms :< git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65436 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- process.c | 96 +++++++++++++++++++++------------------------------------------ 1 file changed, 31 insertions(+), 65 deletions(-) (limited to 'process.c') diff --git a/process.c b/process.c index 9ee245cba9..4448f26c7b 100644 --- a/process.c +++ b/process.c @@ -3872,8 +3872,7 @@ COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) static rb_pid_t retry_fork_async_signal_safe(int *status, int *ep, int (*chfunc)(void*, char *, size_t), void *charg, - char *errmsg, size_t errmsg_buflen, - struct waitpid_state *w) + char *errmsg, size_t errmsg_buflen) { rb_pid_t pid; volatile int try_gc = 1; @@ -3883,9 +3882,6 @@ retry_fork_async_signal_safe(int *status, int *ep, while (1) { prefork(); disable_child_handler_before_fork(&old); - if (w && WAITPID_USE_SIGCHLD) { - rb_native_mutex_lock(&rb_ec_vm_ptr(w->ec)->waitpid_lock); - } #ifdef HAVE_WORKING_VFORK if (!has_privilege()) pid = vfork(); @@ -3910,13 +3906,6 @@ retry_fork_async_signal_safe(int *status, int *ep, #endif } err = errno; - if (w && WAITPID_USE_SIGCHLD) { - if (pid > 0) { - w->pid = pid; - list_add(&rb_ec_vm_ptr(w->ec)->waiting_pids, &w->wnode); - } - rb_native_mutex_unlock(&rb_ec_vm_ptr(w->ec)->waitpid_lock); - } disable_child_handler_fork_parent(&old); if (0 < pid) /* fork succeed, parent process */ return pid; @@ -3927,34 +3916,28 @@ retry_fork_async_signal_safe(int *status, int *ep, } COMPILER_WARNING_POP -static rb_pid_t -fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, - VALUE fds, char *errmsg, size_t errmsg_buflen, - struct rb_execarg *eargp) +rb_pid_t +rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, + char *errmsg, size_t errmsg_buflen) { rb_pid_t pid; int err; int ep[2]; int error_occurred; - struct waitpid_state *w; - - w = eargp && eargp->waitpid_state ? eargp->waitpid_state : 0; if (status) *status = 0; if (pipe_nocrash(ep, fds)) return -1; - pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, - errmsg, errmsg_buflen, w); + pid = retry_fork_async_signal_safe(status, ep, chfunc, charg, errmsg, errmsg_buflen); if (pid < 0) return pid; close(ep[1]); error_occurred = recv_child_error(ep[0], &err, errmsg, errmsg_buflen); if (error_occurred) { if (status) { - VM_ASSERT(w == 0 && "only used by extensions"); rb_protect(proc_syswait, (VALUE)pid, status); } - else if (!w) { + else { rb_syswait(pid); } errno = err; @@ -3963,21 +3946,6 @@ fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg, return pid; } -/* - * The "async_signal_safe" name is a lie, but it is used by pty.c and - * maybe other exts. fork() is not async-signal-safe due to pthread_atfork - * and future POSIX revisions will remove it from a list of signal-safe - * functions. rb_waitpid is not async-signal-safe since MJIT, either. - * For our purposes, we do not need async-signal-safety, here - */ -rb_pid_t -rb_fork_async_signal_safe(int *status, - int (*chfunc)(void*, char *, size_t), void *charg, - VALUE fds, char *errmsg, size_t errmsg_buflen) -{ - return fork_check_err(status, chfunc, charg, fds, errmsg, errmsg_buflen, 0); -} - COMPILER_WARNING_PUSH #ifdef __GNUC__ COMPILER_WARNING_IGNORED(-Wdeprecated-declarations) @@ -4266,8 +4234,7 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen) #endif #if defined HAVE_WORKING_FORK && !USE_SPAWNV - pid = fork_check_err(0, rb_exec_atfork, eargp, eargp->redirect_fds, - errmsg, errmsg_buflen, eargp); + pid = rb_fork_async_signal_safe(NULL, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen); #else prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name; @@ -4386,39 +4353,37 @@ rb_spawn(int argc, const VALUE *argv) static VALUE rb_f_system(int argc, VALUE *argv) { - /* - * n.b. using alloca for now to simplify future Thread::Light code - * when we need to use malloc for non-native Fiber - */ - struct waitpid_state *w = alloca(sizeof(struct waitpid_state)); - rb_pid_t pid; /* may be different from waitpid_state.pid on exec failure */ + rb_pid_t pid; + int status; VALUE execarg_obj; struct rb_execarg *eargp; - int exec_errnum; execarg_obj = rb_execarg_new(argc, argv, TRUE, TRUE); TypedData_Get_Struct(execarg_obj, struct rb_execarg, &exec_arg_data_type, eargp); - w->ec = GET_EC(); - waitpid_state_init(w, 0, 0); - eargp->waitpid_state = w; - pid = rb_execarg_spawn(execarg_obj, 0, 0); - exec_errnum = pid < 0 ? errno : 0; - +#if RUBY_SIGCHLD + eargp->nocldwait_prev = ruby_nocldwait; + ruby_nocldwait = 0; +#endif + pid = rb_execarg_spawn(execarg_obj, NULL, 0); #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV) - if (w->pid > 0) { - /* `pid' (not w->pid) may be < 0 here if execve failed in child */ - if (WAITPID_USE_SIGCHLD) { - rb_ensure(waitpid_sleep, (VALUE)w, waitpid_cleanup, (VALUE)w); - } - else { - waitpid_no_SIGCHLD(w); + if (pid > 0) { + int ret, status; + ret = rb_waitpid(pid, &status, 0); + if (ret == (rb_pid_t)-1) { +# if RUBY_SIGCHLD + ruby_nocldwait = eargp->nocldwait_prev; +# endif + RB_GC_GUARD(execarg_obj); + rb_sys_fail("Another thread waited the process started by system()."); } - rb_last_status_set(w->status, w->ret); } #endif - if (w->pid < 0 /* fork failure */ || pid < 0 /* exec failure */) { +#if RUBY_SIGCHLD + ruby_nocldwait = eargp->nocldwait_prev; +#endif + if (pid < 0) { if (eargp->exception) { - int err = exec_errnum ? exec_errnum : w->errnum; + int err = errno; VALUE command = eargp->invoke.sh.shell_script; RB_GC_GUARD(execarg_obj); rb_syserr_fail_str(err, command); @@ -4427,11 +4392,12 @@ rb_f_system(int argc, VALUE *argv) return Qnil; } } - if (w->status == EXIT_SUCCESS) return Qtrue; + status = PST2INT(rb_last_status_get()); + if (status == EXIT_SUCCESS) return Qtrue; if (eargp->exception) { VALUE command = eargp->invoke.sh.shell_script; VALUE str = rb_str_new_cstr("Command failed with"); - rb_str_cat_cstr(pst_message_status(str, w->status), ": "); + rb_str_cat_cstr(pst_message_status(str, status), ": "); rb_str_append(str, command); RB_GC_GUARD(execarg_obj); rb_exc_raise(rb_exc_new_str(rb_eRuntimeError, str)); -- cgit v1.2.3