From owner-freebsd-bugs Thu Jan 25 2:40:20 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id DB60437B401 for ; Thu, 25 Jan 2001 02:40:00 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0PAe0q00318; Thu, 25 Jan 2001 02:40:00 -0800 (PST) (envelope-from gnats) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 8CE4737B401 for ; Thu, 25 Jan 2001 02:33:03 -0800 (PST) Received: (from nobody@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f0PAX3p99537; Thu, 25 Jan 2001 02:33:03 -0800 (PST) (envelope-from nobody) Message-Id: <200101251033.f0PAX3p99537@freefall.freebsd.org> Date: Thu, 25 Jan 2001 02:33:03 -0800 (PST) From: barak@cwnt.com To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: bin/24632: libc_r delicate deviation from libc in handling SIGCHLD Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 24632 >Category: bin >Synopsis: libc_r delicate deviation from libc in handling SIGCHLD >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Jan 25 02:40:00 PST 2001 >Closed-Date: >Last-Modified: >Originator: Barak Enat >Release: FreeBSD 4.2 >Organization: Charlotte's Networks >Environment: FreeBSD simba.cwnt.co.il 4.2-RELEASE FreeBSD 4.2-RELEASE #2: Wed Jan 17 16:22:29 GMT 2001 barak@simba.cwnt.co.il:/usr/src/sys/compile/COMPAQ_DL360 i386 >Description: Hi, By default, all signals behave as if an SA_RESTART flag was set for them. Thus, all system calls will be restarted once the signal handler returns. In practice this means that the EINTR error code should never happen, unless a sigaction call cleared the SA_RESTART flag for some signal. However, this is not true with respect to SIGCHLD and the pthread library. I enountered several cases where a read operation (for example) returned with a -1 and errno = EINTR when a child process terminated. This happened only when I was linking to the libc_r pthread library. Here is a small example (pb.c) and an associated makefile: #include #include int main() { int s; char c; if (! fork()) { char *args[3] = {"/bin/sleep", "10000", 0}; execv(args[0], args); } while (s = read(0, &c, 1)) { if (s < 0) perror("read"); else write(1, &c, 1); } return 0; } all: pb pb_r pb: pb.c cc -o pb pb.c pb_r: pb.c cc -pthread -o pb_r pb.c >How-To-Repeat: To see the problem, the makefile generates both a threaded version (pb_r) and a non threaded version (pb). To reproduce the problem do: 1. Run pb_r. The program forks a child (sleep) process, and then it is a simple echo program. 2. Now type a line or two and let the program echo it. (This is a must - I don't know why the problem isn't revealed otherwise). 3. Now (from another terminal) kill the child process. 4. You should see the following output: > ./pb_r test123 test123 read: Interrupted system call If you try the same with the non threaded program (pb), the read never returns an error. >Fix: Looking at the pthread library code I have noticed that in three places the sa_flags field is initialized without the SA_RESTART flag. By blindly adding the SA_RESTART flag, I was able to solve the issue, however, I'm not sure this is the apropriate approach. (Maybe, instead, all the relevant system calls, such as read, should be fixed to be restarted appon kernel EINTR if the signal flags require it.) Below is the patch I did (again - I'm quite sure it is incomplete). Regards, Barak barak@cwnt.com --- uthread/uthread_init.c Thu Jan 25 12:19:07 2001 +++ uthread/uthread_init.c.orig Thu Nov 16 22:21:50 2000 @@ -271,9 +271,9 @@ /* Initialise the global signal action structure: */ sigfillset(&act.sa_mask); act.sa_handler = (void (*) ()) _thread_sig_handler; - act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; + act.sa_flags = SA_SIGINFO | SA_ONSTACK; /* Clear pending signals for the process: */ sigemptyset(&_process_sigpending); --- uthread/uthread_sigaction.c Thu Jan 25 12:19:07 2001 +++ uthread/uthread_sigaction.c.orig Fri Nov 10 01:46:04 2000 @@ -79,9 +79,9 @@ * by other signals. Always request the POSIX signal * handler arguments. */ sigfillset(&gact.sa_mask); - gact.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; + gact.sa_flags = SA_SIGINFO | SA_ONSTACK; /* * Check if the signal handler is being set to * the default or ignore handlers: --- uthread/uthread_signal.c Thu Jan 25 12:19:07 2001 +++ uthread/uthread_signal.c.orig Fri Nov 10 01:46:04 2000 @@ -44,9 +44,9 @@ /* Initialise the signal action structure: */ sigemptyset(&sa.sa_mask); sa.sa_handler = a; - sa.sa_flags = SA_SIGINFO | SA_RESTART; + sa.sa_flags = SA_SIGINFO; /* Perform the sigaction syscall: */ if (_thread_sys_sigaction(s, &sa, &osa) < 0) { /* Return an error: */ >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message