Skip site navigation (1)Skip section navigation (2)
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>