Hi, I come across the following problem: after fork(), the 5-STABLE system sets the child process blocked signal mask to 0 (let us account single-threaded processes only). I was under impression that signal mask shall be inherited by the child process (according to SUSv3 and man fork). Inheritance _was_ the behaviour of 4-STABLE (there, p_sigmask belongs to struct proc and placed in the copied-on-fork part of the structure) and also seen on other UNIXes (e.g. Solaris).
After googling, I found the comment by Dong Xuezhang in http://lists.freebsd.org/pipermail/freebsd-threads/2005-February/002899.html where he said that "Actually fork() do not copy the properties of signal mask". I confirm that fork does not copy mask, but why ? Attached is the program that illustrates this issue on pooma% uname -a ~/work/bsd/sigmask FreeBSD pooma.home 5.4-STABLE FreeBSD 5.4-STABLE #32: Fri Apr 15 22:16:43 EEST 2005 [EMAIL PROTECTED]:/usr/obj/usr/src/sys/POOMA i386 On unpatched 5-STABLE, the child process reports SIGUSR2 immediately after start, despite parent blocked SIGUSR2 before forking. It seems that needs of thread_schedule_upcall() to zero sigmask interfere with the needs of the fork1(). I propose the trivial patch (against 5-STABLE) to fix the problems. It handles td_sigmask in the way similar to td_sigstk, that is also zeroed on _upcall(), as was done by davidxu at kern/kern_fork.c:1.209 rev. Index: kern/kern_fork.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/kern_fork.c,v retrieving revision 1.234.2.8 diff -U5 -r1.234.2.8 kern_fork.c --- kern/kern_fork.c 27 Feb 2005 02:36:39 -0000 1.234.2.8 +++ kern/kern_fork.c 18 Apr 2005 08:58:50 -0000 @@ -470,10 +470,11 @@ __rangeof(struct thread, td_startcopy, td_endcopy)); bcopy(&td->td_ksegrp->kg_startcopy, &kg2->kg_startcopy, __rangeof(struct ksegrp, kg_startcopy, kg_endcopy)); td2->td_sigstk = td->td_sigstk; + td2->td_sigmask = td->td_sigmask; /* * Duplicate sub-structures as needed. * Increase reference counts on shared objects. */ Thanks for attention, Kostik Belousov.
#include <unistd.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h> #include <string.h> #include <stdio.h> extern "C" void sigusr2_handler(int signo) { static const char msg[] = "SIGUSR2\n"; write(2, msg, sizeof(msg) - 1); _exit(0); } int main(int argc, char *argv[]) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigusr2_handler; sigaction(SIGUSR2, &sa, NULL); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGUSR2); sigprocmask(SIG_BLOCK, &mask, NULL); pid_t child = fork(); if (child == 0) { raise(SIGUSR2); printf("sleeping\n"); sleep(10); printf("enabling SIGUSR2\n"); sigprocmask(SIG_UNBLOCK, &mask, NULL); while (true) ; } int status; wait(&status); return 0; }
_______________________________________________ freebsd-hackers@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-hackers To unsubscribe, send any mail to "[EMAIL PROTECTED]"