[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: