Skip to content

Commit 88f7a52

Browse files
committed
Wake up libuv main loop on SIGINT
1 parent 28764be commit 88f7a52

File tree

6 files changed

+34
-0
lines changed

6 files changed

+34
-0
lines changed

src/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ void _julia_init(JL_IMAGE_SEARCH rel)
544544
ios_set_io_wait_func = jl_set_io_wait;
545545
jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.),
546546
// best to call this first, since it also initializes libuv
547+
jl_init_signal_async();
547548
restore_signals();
548549
jl_resolve_sysimg_location(rel);
549550
// loads sysimg if available, and conditionally sets jl_options.cpu_target

src/jl_uv.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@
4747
extern "C" {
4848
#endif
4949

50+
static uv_async_t signal_async;
51+
52+
static void jl_signal_async_cb(uv_async_t *hdl)
53+
{
54+
// This should abort the current loop and the julia code it returns to
55+
// or the safepoint in the callers of `uv_run` should throw the exception.
56+
(void)hdl;
57+
uv_stop(jl_io_loop);
58+
}
59+
60+
void jl_wake_libuv(void)
61+
{
62+
uv_async_send(&signal_async);
63+
}
64+
65+
void jl_init_signal_async(void)
66+
{
67+
uv_async_init(jl_io_loop, &signal_async, jl_signal_async_cb);
68+
}
69+
5070
extern jl_module_t *jl_old_base_module;
5171
static jl_value_t *close_cb = NULL;
5272

@@ -80,6 +100,8 @@ JL_DLLEXPORT void jl_uv_closeHandle(uv_handle_t *handle)
80100
// also let the client app do its own cleanup
81101
if (handle->type != UV_FILE && handle->data)
82102
jl_uv_call_close_callback((jl_value_t*)handle->data);
103+
if (handle == (uv_handle_t*)&signal_async)
104+
return;
83105
free(handle);
84106
}
85107

@@ -114,6 +136,7 @@ JL_DLLEXPORT int jl_run_once(uv_loop_t *loop)
114136
{
115137
if (loop) {
116138
loop->stop_flag = 0;
139+
jl_gc_safepoint();
117140
return uv_run(loop,UV_RUN_ONCE);
118141
}
119142
else return 0;
@@ -123,6 +146,7 @@ JL_DLLEXPORT void jl_run_event_loop(uv_loop_t *loop)
123146
{
124147
if (loop) {
125148
loop->stop_flag = 0;
149+
jl_gc_safepoint();
126150
uv_run(loop,UV_RUN_DEFAULT);
127151
}
128152
}
@@ -131,6 +155,7 @@ JL_DLLEXPORT int jl_process_events(uv_loop_t *loop)
131155
{
132156
if (loop) {
133157
loop->stop_flag = 0;
158+
jl_gc_safepoint();
134159
return uv_run(loop,UV_RUN_NOWAIT);
135160
}
136161
else return 0;

src/julia_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ void jl_init_root_task(void *stack, size_t ssize);
255255
void jl_init_serializer(void);
256256
void jl_gc_init(void);
257257
void jl_init_restored_modules(jl_array_t *init_order);
258+
void jl_init_signal_async(void);
258259

259260
void _julia_init(JL_IMAGE_SEARCH rel);
260261
#ifdef COPY_STACKS
@@ -309,6 +310,7 @@ void jl_safepoint_defer_sigint(void);
309310
// Return `1` if the sigint should be delivered and `0` if there's no sigint
310311
// to be delivered.
311312
int jl_safepoint_consume_sigint(void);
313+
void jl_wake_libuv(void);
312314

313315
#ifdef JULIA_ENABLE_THREADING
314316
jl_get_ptls_states_func jl_get_ptls_states_getter(void);

src/signals-mach.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ static void jl_try_deliver_sigint(void)
293293
jl_clear_force_sigint();
294294
jl_throw_in_thread(0, thread, jl_interrupt_exception);
295295
}
296+
else {
297+
jl_wake_libuv();
298+
}
296299

297300
ret = thread_resume(thread);
298301
HANDLE_MACH_ERROR("thread_resume", ret);

src/signals-unix.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ static void jl_try_deliver_sigint(void)
172172
{
173173
jl_tls_states_t *ptls = jl_all_task_states[0].ptls;
174174
jl_safepoint_enable_sigint();
175+
jl_wake_libuv();
175176
jl_atomic_store_release(&ptls->signal_request, 2);
176177
// This also makes sure `sleep` is aborted.
177178
pthread_kill(jl_all_task_states[0].system_id, SIGUSR2);

src/signals-win.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static void jl_try_throw_sigint(void)
4545
{
4646
jl_tls_states_t *ptls = jl_get_ptls_states();
4747
jl_safepoint_enable_sigint();
48+
jl_wake_libuv();
4849
int force = jl_check_force_sigint();
4950
if (force || (!ptls->defer_signal && ptls->io_wait)) {
5051
jl_safepoint_consume_sigint();
@@ -127,6 +128,7 @@ static void jl_try_deliver_sigint(void)
127128
{
128129
jl_tls_states_t *ptls = jl_all_task_states[0].ptls;
129130
jl_safepoint_enable_sigint();
131+
jl_wake_libuv();
130132
if ((DWORD)-1 == SuspendThread(hMainThread)) {
131133
// error
132134
jl_safe_printf("error: SuspendThread failed\n");

0 commit comments

Comments
 (0)