94084c
commit 73c7f5a87971de2797f261e1a447f68dce09284b
94084c
Author: Florian Weimer <fweimer@redhat.com>
94084c
Date:   Mon Sep 20 14:56:08 2021 +0200
94084c
94084c
    nptl: pthread_kill needs to return ESRCH for old programs (bug 19193)
94084c
    
94084c
    The fix for bug 19193 breaks some old applications which appear
94084c
    to use pthread_kill to probe if a thread is still running, something
94084c
    that is not supported by POSIX.
94084c
    
94084c
    (cherry picked from commit 95dba35bf05e4a5d69dfae5e9c9d4df3646a7f93)
94084c
94084c
diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
94084c
index fb7862eff787a94f..a44dc8f2d9baa925 100644
94084c
--- a/nptl/pthread_kill.c
94084c
+++ b/nptl/pthread_kill.c
94084c
@@ -21,8 +21,11 @@
94084c
 #include <pthreadP.h>
94084c
 #include <shlib-compat.h>
94084c
 
94084c
-int
94084c
-__pthread_kill_internal (pthread_t threadid, int signo)
94084c
+/* Sends SIGNO to THREADID.  If the thread is about to exit or has
94084c
+   already exited on the kernel side, return NO_TID.  Otherwise return
94084c
+   0 or an error code. */
94084c
+static int
94084c
+__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid)
94084c
 {
94084c
   struct pthread *pd = (struct pthread *) threadid;
94084c
   if (pd == THREAD_SELF)
94084c
@@ -52,11 +55,8 @@ __pthread_kill_internal (pthread_t threadid, int signo)
94084c
        signal is either not observable (the target thread has already
94084c
        blocked signals at this point), or it will fail, or it might be
94084c
        delivered to a new, unrelated thread that has reused the TID.
94084c
-       So do not actually send the signal.  Do not report an error
94084c
-       because the threadid argument is still valid (the thread ID
94084c
-       lifetime has not ended), and ESRCH (for example) would be
94084c
-       misleading.  */
94084c
-    ret = 0;
94084c
+       So do not actually send the signal.  */
94084c
+    ret = no_tid;
94084c
   else
94084c
     {
94084c
       /* Using tgkill is a safety measure.  pd->exit_lock ensures that
94084c
@@ -71,6 +71,15 @@ __pthread_kill_internal (pthread_t threadid, int signo)
94084c
   return ret;
94084c
 }
94084c
 
94084c
+int
94084c
+__pthread_kill_internal (pthread_t threadid, int signo)
94084c
+{
94084c
+  /* Do not report an error in the no-tid case because the threadid
94084c
+     argument is still valid (the thread ID lifetime has not ended),
94084c
+     and ESRCH (for example) would be misleading.  */
94084c
+  return __pthread_kill_implementation (threadid, signo, 0);
94084c
+}
94084c
+
94084c
 int
94084c
 __pthread_kill (pthread_t threadid, int signo)
94084c
 {
94084c
@@ -81,6 +90,7 @@ __pthread_kill (pthread_t threadid, int signo)
94084c
 
94084c
   return __pthread_kill_internal (threadid, signo);
94084c
 }
94084c
+
94084c
 /* Some architectures (for instance arm) might pull raise through libgcc, so
94084c
    avoid the symbol version if it ends up being used on ld.so.  */
94084c
 #if !IS_IN(rtld)
94084c
@@ -88,6 +98,17 @@ libc_hidden_def (__pthread_kill)
94084c
 versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34);
94084c
 
94084c
 # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34)
94084c
-compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0);
94084c
+/* Variant which returns ESRCH in the no-TID case, for backwards
94084c
+   compatibility.  */
94084c
+int
94084c
+attribute_compat_text_section
94084c
+__pthread_kill_esrch (pthread_t threadid, int signo)
94084c
+{
94084c
+  if (__is_internal_signal (signo))
94084c
+    return EINVAL;
94084c
+
94084c
+  return __pthread_kill_implementation (threadid, signo, ESRCH);
94084c
+}
94084c
+compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0);
94084c
 # endif
94084c
 #endif
94084c
diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c
94084c
index 7575fb6d58cae99c..a2fddad526666c8c 100644
94084c
--- a/sysdeps/pthread/tst-pthread_kill-exited.c
94084c
+++ b/sysdeps/pthread/tst-pthread_kill-exited.c
94084c
@@ -16,11 +16,15 @@
94084c
    License along with the GNU C Library; if not, see
94084c
    <https://www.gnu.org/licenses/>.  */
94084c
 
94084c
-/* This test verifies that pthread_kill returns 0 (and not ESRCH) for
94084c
-   a thread that has exited on the kernel side.  */
94084c
+/* This test verifies that the default pthread_kill returns 0 (and not
94084c
+   ESRCH) for a thread that has exited on the kernel side.  */
94084c
 
94084c
+#include <errno.h>
94084c
+#include <pthread.h>
94084c
+#include <shlib-compat.h>
94084c
 #include <signal.h>
94084c
 #include <stddef.h>
94084c
+#include <support/check.h>
94084c
 #include <support/support.h>
94084c
 #include <support/xthread.h>
94084c
 
94084c
@@ -30,6 +34,12 @@ noop_thread (void *closure)
94084c
   return NULL;
94084c
 }
94084c
 
94084c
+#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC
94084c
+extern __typeof (pthread_kill) compat_pthread_kill;
94084c
+compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill,
94084c
+                         GLIBC_2_0);
94084c
+#endif
94084c
+
94084c
 static int
94084c
 do_test (void)
94084c
 {
94084c
@@ -37,7 +47,14 @@ do_test (void)
94084c
 
94084c
   support_wait_for_thread_exit ();
94084c
 
94084c
+  /* NB: Always uses the default symbol due to separate compilation.  */
94084c
   xpthread_kill (thr, SIGUSR1);
94084c
+
94084c
+#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC
94084c
+  /* Old binaries need the non-conforming ESRCH error code.  */
94084c
+  TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH);
94084c
+#endif
94084c
+
94084c
   xpthread_join (thr);
94084c
 
94084c
   return 0;