Bug#66803: [PATCH] Problem with signals and LinuxThreads.
Package: libc6
Version: 2.1.3-10
Severity: normal
[This report was also sent to the upstream maintainers. I'm filing it
also with the Debian BTS for completeness and possibly a quicker fix.]
Description
-----------
As mentioned in the BUGS file [i.e. /usr/share/doc/libc6/BUGS.gz],
there are problems with signal handling when using LinuxThreads. One
of them is in sysdeps/posix/signal.c:
libpthread overrides glibc's sigaction() function (which is declared
as a weak alias in glibc) and provides its own (see
linuxthreads/signal.c). This custom function stores the old signal
handler in a custom struct. Now glibc's signal() function ultimately
calls __sigaction(), a glibc internal function that calls Linux'
rt_sigaction() syscall, *without* calling LinuxThreads' overloaded
sigaction() function. Of course, the returned signal handler is
different than the actual signal handler.
Imagine a case where a threaded application (let's call it nscd)
sets up a signal handler (SIG_IGN) for SIGPIPE using sigaction().
Now this application uses a library (let's call this one
libnss_pgsql/libpgsql) that also wants to protect against I/O errors
and sets up a signal handler (SIG_IGN) for SIGPIPE using signal()
just before doing I/O. Now, because of the bug, signal() does not
return the real signal handler but the SIG_DFL handler. After doing
I/O the library tries to re-set the handler to the one returned by
the former signal() call - the wrong one! This leads to nscd exiting
if there is an I/O error. (Like pressing CTRL-C while doing "ls -l".)
Kudos go to Michael Karcher for hunting down the actual location of the
bug.
How to Repeat
-------------
srittau@moby:~$ cat sig.c
#include <stdio.h>
#include <signal.h>
int main()
{
struct sigaction old;
signal(SIGPIPE, SIG_IGN);
sigaction(SIGPIPE, NULL, &old);
printf("%p\n", old.sa_handler);
return 0;
}
srittau@moby:~$ gcc sig.c -o sig
srittau@moby:~$ ./sig
0x1 [i.e. SIG_IGN]
srittau@moby:~$ gcc sig.c -o sig -lpthread
srittau@moby:~$ ./sig
(nil) [i.e. SIG_DFL]
srittau@moby:~$
Fix
---
Apply the following patch (by Michael) to sysdeps/posix/signal.c:
--- glibc-2.1.3/sysdeps/posix/signal.c.buggy Thu Jul 6 10:25:00 2000
+++ glibc-2.1.3/sysdeps/posix/signal.c Thu Jul 6 10:25:18 2000
@@ -43,7 +43,7 @@
if (__sigemptyset (&act.sa_mask) < 0)
return SIG_ERR;
act.sa_flags = __sigismember (&_sigintr, sig) ? 0 : SA_RESTART;
- if (__sigaction (sig, &act, &oact) < 0)
+ if (sigaction (sig, &act, &oact) < 0)
return SIG_ERR;
return oact.sa_handler;
This patch causes signal() to use the weak sigaction() function which
can be overloaded by libraries like libpthread.
- Sebastian
-- System Information
Debian Release: 2.2
Architecture: i386
Kernel: Linux moby 2.4.0-test2 #1 Don Jun 29 19:05:32 CEST 2000 i686
Versions of packages libc6 depends on:
ii ldso 1.9.11-9 The Linux dynamic linker, library
Reply to: