diff options
Diffstat (limited to 'mjit.c')
-rw-r--r-- | mjit.c | 48 |
1 files changed, 37 insertions, 11 deletions
@@ -80,6 +80,7 @@ #include "constant.h" #include "id_table.h" #include "ruby_assert.h" +#include "ruby/thread.h" #include "ruby/util.h" #include "ruby/version.h" @@ -118,6 +119,10 @@ 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 */ +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 @@ -401,22 +406,40 @@ start_process(const char *path, char *const *argv) static int exec_process(const char *path, char *const argv[]) { - int stat, exit_code; + int stat, exit_code = -2; pid_t pid; + rb_vm_t *vm = RUBY_SIGCHLD ? GET_VM() : 0; + rb_nativethread_cond_t cond; - pid = start_process(path, argv); - if (pid <= 0) - return -2; + if (vm) { + rb_native_cond_initialize(&cond); + rb_native_mutex_lock(&vm->waitpid_lock); + } - for (;;) { - waitpid(pid, &stat, 0); - if (WIFEXITED(stat)) { - exit_code = WEXITSTATUS(stat); - break; - } else if (WIFSIGNALED(stat)) { - exit_code = -1; + 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, "[%d] waitpid(%d): %s\n", + getpid(), pid, strerror(errno)); 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; } @@ -1491,12 +1514,15 @@ 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); } } |