| Summary: | libc_r delicate deviation from libc in handling SIGCHLD | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | barak <barak> | ||||||
| Component: | threads | Assignee: | freebsd-threads (Nobody) <threads> | ||||||
| Status: | Closed FIXED | ||||||||
| Severity: | Affects Only Me | ||||||||
| Priority: | Normal | ||||||||
| Version: | Unspecified | ||||||||
| Hardware: | Any | ||||||||
| OS: | Any | ||||||||
| Attachments: |
|
||||||||
Responsible Changed From-To: freebsd-bugs->freebsd-threads Assign to threads mailing list 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. 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. 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). |
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.