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