From owner-freebsd-questions@FreeBSD.ORG Tue May 21 05:24:30 2013 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 82E6E1BA for ; Tue, 21 May 2013 05:24:30 +0000 (UTC) (envelope-from noel.hunt@gmail.com) Received: from mail-we0-x22e.google.com (mail-we0-x22e.google.com [IPv6:2a00:1450:400c:c03::22e]) by mx1.freebsd.org (Postfix) with ESMTP id 097A2B6 for ; Tue, 21 May 2013 05:24:29 +0000 (UTC) Received: by mail-we0-f174.google.com with SMTP id x53so95951wes.19 for ; Mon, 20 May 2013 22:24:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:date:message-id:subject:from:to:content-type; bh=VXLodTbtHtwMc7XcSlhnyf54+hgyRt1sKqlPZYHFYZA=; b=bafPs+FoMW73OjqboXqXOw15YdqqBNWUf+fbzJVS3/M0sDd3T9RSYm1j0pxV796jaY ZAG3/iGZ7ya1Jyj0Bqr1+GEUQefxNcAo8zWejgjeEV0hY9AtGo0LxXL38HrZWCWLh3RO X5FRHMm8T03KfeowdyLSPGJQNpJWcgWOTOYmLV7JKgMkdYdKaudydoMYhqAUpgZ1oYao y1kibt40n9/6EZyU5MrALPIYwb8RExc2+01Uzz0T99TwNXamUb+v7QGh8omHKgTl0jXp bGTe7CX62R0zrsQXWiMsWOxri5Qn/DHoAdV27PzwmzzcYaFtHF2k/TGYqqjCDubG7283 K/tQ== MIME-Version: 1.0 X-Received: by 10.180.108.168 with SMTP id hl8mr1201078wib.23.1369113866600; Mon, 20 May 2013 22:24:26 -0700 (PDT) Received: by 10.180.108.106 with HTTP; Mon, 20 May 2013 22:24:26 -0700 (PDT) Date: Tue, 21 May 2013 15:24:26 +1000 Message-ID: Subject: signal vs. sigaction and SIGCHLD From: Noel Hunt To: freebsd-questions@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 X-Content-Filtered-By: Mailman/MimeDel 2.1.14 X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 May 2013 05:24:30 -0000 I have a small test program which simply forks and execs its command line arguments, but after the fork and before the exec, it sends a SIGSTOP to the child. The parent then sleeps for 3 seconds before exiting. However, a signal handler for SIGCHLD has been installed and I was expecting the parent to be notified of the SIGSTOP sent to the child, but with the `signal' interface this doesn't appear to work. If I change the code to use `sigaction' and `sigprocmask' (to unblock any blocked SIGCHLD), this program works the way intended, that is, the signal handler is called: 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 10 #define SIGACTION 11 12 static void waithandler(int i){ 13 int pid, cursig; 14 int tstat; 15 16 #ifdef SIGACTION 17 pid = waitpid(-1, &tstat, WUNTRACED); 18 #else 19 pid = wait(&tstat); 20 signal(SIGCHLD, waithandler); 21 #endif 22 if (pid < 0) 23 return; 24 25 printf("waithandler: child (%d)", pid); 26 if (WIFSTOPPED(tstat)) { 27 printf(" received"); 28 cursig = WSTOPSIG(tstat); 29 if (cursig == SIGSTOP) 30 printf(" SIGSTOP\n"); 31 else if (cursig == SIGTRAP) 32 printf(" SIGTRAP\n"); 33 else 34 printf(" %d\n", cursig); 35 } else { 36 printf(" exited status=%d\n", WEXITSTATUS(tstat)); 37 } 38 } 39 40 main(int argc, char **argv){ 41 int i, j; 42 int fd, hangpid; 43 FILE *ttyerr; 44 char ctl[16]; 45 #ifdef SIGACTION 46 sigset_t sigmask[2]; 47 struct sigaction sa; 48 49 sa.sa_flags = 0; 50 sigemptyset(&sa.sa_mask); 51 sa.sa_handler = waithandler; 52 sigaction(SIGCHLD, &sa, NULL); 53 sigemptyset(&sigmask[0]); 54 sigaddset(&sigmask[0], SIGCHLD); 55 sigprocmask(SIG_UNBLOCK, &sigmask[0], &sigmask[1]); 56 #else 57 58 signal(SIGCHLD, waithandler); 59 #endif 60 ttyerr = fopen("/dev/tty", "w"); 61 if (argc <= 1) { 62 if( ttyerr ) 63 fprintf(ttyerr,"Usage: %s cmd [args...]\n",argv[0],*argv); 64 exit(1); 65 } 66 if( (hangpid=fork())==0 ){ 67 kill(getpid(), SIGSTOP); 68 execvp(argv[1], argv+1); 69 perror(argv[1]); 70 exit(1); 71 } 72 if(hangpid==-1){ 73 perror("fork"); 74 exit(1); 75 } 76 if( ttyerr ){ 77 fprintf(ttyerr,"/proc/%d\n",hangpid); 78 fclose(ttyerr); 79 } 80 sleep(3); 81 } The file is `hang.c'. I compile and run it like this: % ./hang echo foo bar baz waithandler: child (2280) received SIGSTOP /proc/2280 If I recompile with `#undef SIGACTION', waithandler is not called. I should add that even with the sigaction(2) interface, without the `sigprocmask' call, it still doesn't work, which suggests that SIGCHLD is being blocked. Can anyone explain why?