diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-12-12 06:58:49 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-12-12 06:58:49 -0800 |
commit | 4f0c5f1273cb756b886f3a63930e8aa8698aa5c2 (patch) | |
tree | 569784ba2e3fcadca9f19cc6961bb5a12a3ad0f5 /signal.c | |
parent | d05841efc07ad0300dbfe2d3f3d67131434a8e3c (diff) | |
download | txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.tar.gz txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.tar.bz2 txr-4f0c5f1273cb756b886f3a63930e8aa8698aa5c2.zip |
Cancel in-progress gc if handling async signal.
If a signal goes off in the middle of gc that is
routed to an async lambda handler, we should cancel
gc, so the handler finds the heap in a good state.
Of course, the handler must not return in this
case, or else the interrupted gc will try to resume.
* gc.c (inprogress): New static flag.
(gc): Increment and decrement inprogress variable.
Abort if re-entered.
(gc_inprogress): New function.
(unmark): Do not clear FREE flags, only REACHABLE.
(gc_cancel): New function.
* gc.h (gc_inprogress, gc_cancel): Declared.
* signal.c (sig_handler): In the async lambda
case, check for an in-progress gc and cancel it.
Diffstat (limited to 'signal.c')
-rw-r--r-- | signal.c | 2 |
1 files changed, 2 insertions, 0 deletions
@@ -94,6 +94,8 @@ static void sig_handler(int sig) if (!in_interrupt && async_sig_enabled) { uw_simple_catch_begin; async_sig_enabled = 0; + if (gc_inprogress()) + gc_cancel(); if (funcall2(lambda, num_fast(sig), t)) sig_deferred |= (1UL << sig); uw_unwind { |