aboutsummaryrefslogtreecommitdiffstats
path: root/mjit.c
diff options
context:
space:
mode:
Diffstat (limited to 'mjit.c')
-rw-r--r--mjit.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/mjit.c b/mjit.c
index 07e9328aff..10aa15fb7f 100644
--- a/mjit.c
+++ b/mjit.c
@@ -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);
}
}