Bug 24632

Summary: libc_r delicate deviation from libc in handling SIGCHLD
Product: Base System Reporter: barak <barak>
Component: threadsAssignee: freebsd-threads (Nobody) <threads>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff
none
file.diff none

Description barak 2001-01-25 10:40:00 UTC
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 <unistd.h>
#include <stdio.h>

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

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
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.
Comment 1 Kris Kennaway freebsd_committer freebsd_triage 2003-07-13 02:33:06 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-threads

Assign to threads mailing list
Comment 2 Craig Rodrigues 2004-02-20 02:52:12 UTC
Hi,

I tried the testcase in bin/24632 under -CURRENT.
I linked against -lc_r, -lthr, and -lpthread.
I could not reproduce the problem in this
testcase.

The patch submitted in this PR is for a very old
version of libc_r.  For example, SA_ONSTACK is not
specified in the signal code in libc_r.
Comment 3 Maxim Konovalov freebsd_committer freebsd_triage 2006-04-24 20:27:30 UTC
State Changed
From-To: open->suspended

In RELENG_5,6 and HEAD libc_r is deprecated in favour of 
libpthread and libthr.  Nobody is working on libc_r bugs 
so mark this PR as suspended.
Comment 4 Alexander Best freebsd_committer freebsd_triage 2010-11-18 21:08:26 UTC
State Changed
From-To: suspended->closed

This issue wasn't reproducable with any threading lib back in 2004 and it isn't 
in 2010 (i checked).