NetBSD-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
pselect and signal handling issue
Hi,
I have an issue with netBSD 5.1. My problem is related to
* http://mail-index.netbsd.org/netbsd-users/2010/07/10/msg006559.html
* http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=43625
but seem the issue isn't fixed.
I'm the developper of yaddns (https://github.com/yaddns/yaddns), a
small program to use dyndns services (no-ip, dyndns.org, ...). I'm
trying to porting yaddns (developped on Linux) on NetBSD but i have
found a problem with pselect and signals handling.
In my program, i install signal handler for SIGHUP, SIGTERM, SIGINT,
SIGUSR1 and SIGUSR2 signals. In this signal handler, i modify global
variables to inform what signal was received. As i want to process
signals only in "waiting state", i use pselect() with a sigset empty.
If pselect() return -1 and errno = EINTR, i known signal was caught.
So, i read global variable to known what signal i've received.
Here the relevent code (purified):
static void sig_handler(int signum)
{
if(signum == SIGTERM || signum == SIGINT)
{
log_notice("Receive SIGTERM or SIGINT. Exit.");
keep_going = 0;
}
/* ... etc ... */
}
{
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = sig_handler;
sigaction(SIGTERM, &sa, NULL);
/* ... repeated for all handling signals ... */
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, NULL);
sigemptyset(&unblocked);
while(1)
{
clock_gettime(CLOCK_MONOTONIC, &tp)
if(pselect(max_fd + 1, &readset, &writeset, NULL,
&timeout, &unblocked) < 0)
{
/* signal was caught ? */
if(errno == EINTR)
{
/* ... check variable set by sig handler ... */
if(!keep_going)
/*... etc ...*/
}
/*... etc ...*/
}
}
On my linux, the mecanism works well but in netbsd, the signal handler
isn't call.
ktrace:
{{{
1008 1 yaddns CALL
pselect(1,0xbfbfebb0,0xbfbfebd0,0,0xbfbfec28,0xbfbfec08)
1008 1 yaddns RET pselect -1 errno 4 Interrupted system call
1008 1 yaddns CALL clock_gettime(3,0xbfbfeaec)
1008 1 yaddns RET clock_gettime 0
1008 1 yaddns CALL
pselect(1,0xbfbfebb0,0xbfbfebd0,0,0xbfbfec28,0xbfbfec08)
}}}
But, if i unblock all signals after pselect() was interrupted by
signal, it works:
if(errno == EINTR)
{
sigfillset(&set);
sigprocmask(SIG_UNBLOCK, &set, NULL);
/* ... etc ... */
ktrace:
{{{
5997 1 yaddns CALL
pselect(1,0xbfbfebc0,0xbfbfebe0,0,0xbfbfec28,0xbfbfec18)
5997 1 yaddns RET pselect -1 errno 4 Interrupted system call
5997 1 yaddns CALL __sigprocmask14(2,0xbfbfeb08,0)
5997 1 yaddns RET __sigprocmask14 0
5997 1 yaddns PSIG SIGINT caught handler=0x80491dc mask=():
code=SI_NOINFO
5997 1 yaddns CALL write(1,0xbb91e000,0x21)
5997 1 yaddns GIO fd 1 wrote 33 bytes
"Receive SIGTERM or SIGINT. Exit.\n"
5997 1 yaddns RET write 33/0x21
5997 1 yaddns CALL setcontext(0xbfbfe7e4)
5997 1 yaddns RET syscall JUSTRETURN
}}}
But accorded to all information have found (man, internet), the signal
is delivered BEFORE the pselect() call returns.
So i think there a problem in kernel code :)
Cheers,
Viallard Anthony.
Home |
Main Index |
Thread Index |
Old Index