Date: Fri, 29 Mar 2002 15:14:46 +0000 From: Nick Barnes <Nick.Barnes@pobox.com> To: =?koi8-r?Q?=E2=C5=D2=A3=DA=CB=CF_=E9=D7=C1=CE?= <iberiozko@infodom.ru> Cc: "'freebsd-questions@freebsd.org'" <freebsd-questions@FreeBSD.ORG> Subject: Re: execl() after fork() in signal handler - strange things happen :) Message-ID: <33453.1017414886@thrush.ravenbrook.com> In-Reply-To: Message from =?koi8-r?Q?=E2=C5=D2=A3=DA=CB=CF_=E9=D7=C1=CE?= <iberiozko@infodom.ru> of "Fri, 29 Mar 2002 14:22:31 %2B0300." <3649F9FBD2621F4498A022E513C5CA2101528B@falcon.win.infodom.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
[brought over to -questions from -stable] At 2002-03-29 11:22:31+0000, =?koi8-r?Q?=E2=C5=D2=A3=DA=CB=CF_=E9=D7=C1=CE?= wr ites: > Hello, people. > > The problem is - when doing execl() after fork() inside a signal handler, > the signal is not delivered to executed child anymore. Is this correct? (I > understand, that doing such things is a bad idea, but... :) It's because the signal is blocked in the signal handler (see signal(3)). The signal mask is inherited by the execl child (see sigprocmask(2)), so the signal is still masked in the child. Here's a small modification of your program which shows this. Nick Barnes Ravenbrook Limited #include <stdio.h> #include <unistd.h> #include <signal.h> #include <syslog.h> static char * self; static int running; static void sig_handler(int); static void showmask(void); int main(int argc, char** argv) { int i; self = argv[0]; openlog("signaltest", LOG_PID | LOG_NDELAY, LOG_LOCAL0); showmask(); syslog(LOG_NOTICE, "setting signal handlers"); signal(SIGHUP, sig_handler); signal(SIGTERM, sig_handler); syslog(LOG_NOTICE, "entering waiting loop"); running = 1; i = 0; while(running) { sleep(2); syslog(LOG_NOTICE, "sleeping: %d", i++); } syslog(LOG_NOTICE, "terminated"); return 0; } static void showmask(void) { sigset_t set; int i, mask = sigprocmask(0, NULL, &set); for (i = 1; i < _SIG_MAXSIG; ++i) { if (sigismember(&set, i)) { syslog(LOG_NOTICE, "signal %d (%s) masked\n", i, strsignal(i)); } } } static void sig_handler(int sig) { int rc; syslog(LOG_NOTICE, "got a signal: %d", sig); switch(sig) { case SIGHUP: rc = fork(); if (-1 == rc) { syslog(LOG_ERR, "fork() failed: %m"); break; } if (0 == rc) { rc = execl(self, NULL); syslog(LOG_ERR, "execl() failed: %m"); } case SIGTERM: running = 0; break; } } /* shell log: $ cc -g foo.c $ ./a.out & Mar 29 15:09:16 thrush signaltest[33442]: setting signal handlers Mar 29 15:09:16 thrush signaltest[33442]: entering waiting loop Mar 29 15:09:18 thrush signaltest[33442]: sleeping: 0 Mar 29 15:09:20 thrush signaltest[33442]: sleeping: 1 $ kill -HUP 33442 Mar 29 15:09:22 thrush signaltest[33442]: got a signal: 1 Mar 29 15:09:22 thrush signaltest[33442]: sleeping: 2 Mar 29 15:09:22 thrush signaltest[33442]: terminated Mar 29 15:09:22 thrush signaltest[33444]: signal 1 (Hangup) masked Mar 29 15:09:22 thrush signaltest[33444]: setting signal handlers Mar 29 15:09:22 thrush signaltest[33444]: entering waiting loop Mar 29 15:09:24 thrush signaltest[33444]: sleeping: 0 Mar 29 15:09:26 thrush signaltest[33444]: sleeping: 1 Mar 29 15:09:28 thrush signaltest[33444]: sleeping: 2 $ kill -HUP 33444 Mar 29 15:09:30 thrush signaltest[33444]: sleeping: 3 Mar 29 15:09:32 thrush signaltest[33444]: sleeping: 4 Mar 29 15:09:34 thrush signaltest[33444]: sleeping: 5 $ kill -TERM 33444 Mar 29 15:09:36 thrush signaltest[33444]: got a signal: 15 Mar 29 15:09:36 thrush signaltest[33444]: sleeping: 6 Mar 29 15:09:36 thrush signaltest[33444]: terminated $ */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?33453.1017414886>