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