]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nptl: Use SA_RESTART for SIGCANCEL handler
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Thu, 17 Jun 2021 12:45:03 +0000 (09:45 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 23 Jun 2021 16:45:13 +0000 (13:45 -0300)
The usage of signals to implementation pthread cancellation is an
implementation detail and should not be visible through cancellation
entrypoints.

However now that pthread_cancel always send the SIGCANCEL, some
entrypoint might be interruptable and return EINTR to the caller
(for instance on sem_wait).

Using SA_RESTART hides this, since the cancellation handler should
either act uppon cancellation (if asynchronous cancellation is enable)
or ignore the cancellation internal signal.

Checked on x86_64-linux-gnu and i686-linux-gnu.

NEWS
nptl/pthread_cancel.c

diff --git a/NEWS b/NEWS
index d64be288dac00b8f89a4ae1a65c7265cdc1459a9..48d77d706fc508c9e751c63b2397a6e91854190e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -64,6 +64,14 @@ Deprecated and removed features, and other changes affecting compatibility:
 * The function pthread_yield has been deprecated; programs should use
   the equivalent standard function sched_yield instead.
 
+* The pthread cancellation handler is now installed with SA_RESTART and
+  pthread_cancel will always send the internal SIGCANCEL on a cancellation
+  request.  It should not be visible to application since the cancellation
+  handler should either act upon cancellation (if asynchronous cancellation
+  is enabled) or ignore the cancellation internal signal.  However there are
+  buggy kernel interfaces (for instance some CIFS version) that could still
+  see spurious EINTR error when cancellation interrupts a blocking syscall.
+
 Changes to build and runtime requirements:
 
 * On Linux, the shm_open, sem_open, and related functions now expect the
index 0698cd2046d1362ce94b7d502a9153e71ca0ca87..cc25ff21f364e8a4dffccc75b70fe852501a7884 100644 (file)
@@ -72,7 +72,11 @@ __pthread_cancel (pthread_t th)
     {
       struct sigaction sa;
       sa.sa_sigaction = sigcancel_handler;
-      sa.sa_flags = SA_SIGINFO;
+      /* The signal handle should be non-interruptible to avoid the risk of
+        spurious EINTR caused by SIGCANCEL sent to process or if
+        pthread_cancel() is called while cancellation is disabled in the
+        target thread.  */
+      sa.sa_flags = SA_SIGINFO | SA_RESTART;
       __sigemptyset (&sa.sa_mask);
       __libc_sigaction (SIGCANCEL, &sa, NULL);
       atomic_store_relaxed (&init_sigcancel, 1);