[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
scratch/igc ceec5ace134: Avoid MPS being interrupted by signals
From: |
Pip Cet |
Subject: |
scratch/igc ceec5ace134: Avoid MPS being interrupted by signals |
Date: |
Sun, 22 Dec 2024 17:17:05 -0500 (EST) |
branch: scratch/igc
commit ceec5ace134081b64dbf46c4fb5702ef5209c5fd
Author: Pip Cet <pipcet@protonmail.com>
Commit: Pip Cet <pipcet@protonmail.com>
Avoid MPS being interrupted by signals
* src/igc.c (make_igc): Save signal mask.
(gc_signal_handler_can_run, gc_maybe_quit): New functions.
* src/lisp.h (gc_maybe_quit, gc_signal_handler_can_run):
New functions.
(maybe_quit): Call `gc_maybe_quit'.
* src/sysdep.c (deliver_process_signal, deliver_thread_signal):
Call `gc_signal_handler_can_run'.
---
src/igc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
src/lisp.h | 12 ++++++++++++
src/sysdep.c | 4 ++++
3 files changed, 65 insertions(+)
diff --git a/src/igc.c b/src/igc.c
index eb72406e529..136667aefea 100644
--- a/src/igc.c
+++ b/src/igc.c
@@ -805,6 +805,15 @@ struct igc
/* Registered threads. */
struct igc_thread_list *threads;
+
+ /* Flag to indicate a signal might be pending. */
+ int signals_pending;
+ /* Per-signal flags. These are `int' to reduce the chance of
+ * corruption when accessed non-atomically. */
+ int pending_signals[64];
+ /* The real signal mask we want to restore after handling pending
+ * signals. */
+ sigset_t signal_mask;
};
static bool process_one_message (struct igc *gc);
@@ -4593,6 +4602,7 @@ make_igc (void)
gc->weak_hash_pool = make_pool_awl (gc, gc->weak_hash_fmt,
weak_hash_find_dependent);
gc->immovable_fmt = make_dflt_fmt (gc);
gc->immovable_pool = make_pool_ams (gc, gc->immovable_fmt);
+ sigprocmask(SIG_BLOCK, NULL, &gc->signal_mask);
#ifndef IN_MY_FORK
root_create_pure (gc);
@@ -4903,6 +4913,45 @@ igc_busy_p (void)
return mps_arena_busy (global_igc->arena);
}
+/* Return false if this is an inconvenient time to receive signal SIG;
+ * also arrange for it to be re-raised at a more convenient time in that
+ * case. */
+bool
+gc_signal_handler_can_run (int sig)
+{
+ eassume (sig >= 0);
+ eassert (sig < ARRAYELTS (global_igc->pending_signals));
+ if (igc_busy_p ())
+ {
+ sigset_t sigs;
+ global_igc->signals_pending = 1;
+ global_igc->pending_signals[sig] = 1;
+ sigemptyset (&sigs);
+ sigaddset (&sigs, sig);
+ pthread_sigmask (SIG_BLOCK, &sigs, NULL);
+ /* We cannot raise (sig) here, because there are platforms where
+ * it doesn't work. */
+ return false;
+ }
+ return true;
+}
+
+/* Called from `maybe_quit'. This assumes no signals are blocked. */
+void
+gc_maybe_quit (void)
+{
+ while (global_igc->signals_pending)
+ {
+ global_igc->signals_pending = 0;
+ for (int i = 0; i < ARRAYELTS (global_igc->pending_signals); i++)
+ if (global_igc->pending_signals[i])
+ {
+ global_igc->pending_signals[i] = 0;
+ raise (i);
+ }
+ pthread_sigmask (SIG_SETMASK, &global_igc->signal_mask, NULL);
+ }
+}
DEFUN ("igc--add-extra-dependency", Figc__add_extra_dependency,
Sigc__add_extra_dependency, 3, 3, 0,
diff --git a/src/lisp.h b/src/lisp.h
index c469793467c..ba688482832 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -46,7 +46,17 @@ INLINE_HEADER_BEGIN
#ifdef HAVE_MPS
union gc_header;
+extern void gc_maybe_quit (void);
+extern bool gc_signal_handler_can_run (int);
#else
+INLINE void gc_maybe_quit (void)
+{
+}
+
+INLINE bool gc_signal_handler_can_run (int sig)
+{
+ return true;
+}
union gc_header { };
#endif
@@ -4232,6 +4242,8 @@ maybe_quit (void)
{
if (!NILP (Vquit_flag) || pending_signals)
probably_quit ();
+
+ gc_maybe_quit ();
}
/* Process a quit rarely, based on a counter COUNT, for efficiency.
diff --git a/src/sysdep.c b/src/sysdep.c
index bb4892af4af..9270bfa97d9 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1737,6 +1737,8 @@ static pthread_t main_thread_id;
void
deliver_process_signal (int sig, signal_handler_t handler)
{
+ if (!gc_signal_handler_can_run (sig))
+ return;
/* Preserve errno, to avoid race conditions with signal handlers that
might change errno. Races can occur even in single-threaded hosts. */
int old_errno = errno;
@@ -1772,6 +1774,8 @@ static int thread_backtrace_npointers;
static void
deliver_thread_signal (int sig, signal_handler_t handler)
{
+ if (!gc_signal_handler_can_run (sig))
+ return;
int old_errno = errno;
#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- scratch/igc ceec5ace134: Avoid MPS being interrupted by signals,
Pip Cet <=