]> sourceware.org Git - newlib-cygwin.git/commitdiff
Cygwin: Restore signal handlers on thread cancellation during system()
authorJon Turney <jon.turney@dronecode.org.uk>
Sun, 16 Jul 2023 13:46:00 +0000 (14:46 +0100)
committerJon Turney <jon.turney@dronecode.org.uk>
Tue, 18 Jul 2023 15:43:36 +0000 (16:43 +0100)
Add back the restoration of signal handlers modified during system() on
thread cancellation.

Removed in 3cb9da14 which describes it as 'ill-conceived' (additional
context doesn't appear to be available).

We use the internal implementation helpers for the pthread cleanup
chain, so we can neatly tuck it inside the object, and keep the point
when we restore the signal handlers the same. (The
pthread_cleanup_push/pop() functions are implemented as macros which
must appear in the same lexical scope.)

Fixes: 3cb9da14617c ("Put signals on hold and use system_call_cleanup
class to set and restore signals rather than doing it prior to to
running the program.  Remove the ill-conceived pthread_cleanup stuff.")
Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
winsup/cygwin/spawn.cc

index 84dd74e28fed39b7e1660376ea145a5a54bcf0cd..c16fe269a3454e5824635c6a4a71908cf489ba32 100644 (file)
@@ -228,6 +228,8 @@ struct system_call_handle
   _sig_func_ptr oldint;
   _sig_func_ptr oldquit;
   sigset_t oldmask;
+  __pthread_cleanup_handler cleanup_handler;
+
   bool is_system_call ()
   {
     return oldint != ILLEGAL_SIG_FUNC_PTR;
@@ -253,18 +255,27 @@ struct system_call_handle
        sigaddset (&child_block, SIGCHLD);
        sigprocmask (SIG_BLOCK, &child_block, &oldmask);
        sig_send (NULL, __SIGNOHOLD);
+
+       cleanup_handler = { system_call_handle::cleanup, this, NULL };
+       _pthread_cleanup_push (&cleanup_handler);
       }
   }
   ~system_call_handle ()
   {
     if (is_system_call ())
+      _pthread_cleanup_pop (1);
+  }
+  static void cleanup (void *arg)
+  {
+# define this_ ((system_call_handle *) arg)
+    if (this_->is_system_call ())
       {
-       signal (SIGINT, oldint);
-       signal (SIGQUIT, oldquit);
-       sigprocmask (SIG_SETMASK, &oldmask, NULL);
+       signal (SIGINT, this_->oldint);
+       signal (SIGQUIT, this_->oldquit);
+       sigprocmask (SIG_SETMASK, &(this_->oldmask), NULL);
       }
   }
-# undef cleanup
+# undef this_
 };
 
 child_info_spawn NO_COPY ch_spawn;
This page took 0.032655 seconds and 5 git commands to generate.