Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pthread_sigmask problem

0 views
Skip to first unread message

callum...@db.com

unread,
Feb 4, 2002, 9:06:54 PM2/4/02
to hac...@freebsd.org
Hi all,
I have an application which attempts to block all signals using
pthread_sigmask(). I'm aware that this only works on the current thread,
however this call occurs before any other threads are created and so
should be inherited. I call it as follows:

sigset_t signalSet;

(void)sigfillset(&signalSet);
(void)pthread_sigmask(SIG_BLOCK, &signalSet, NULL);

However, it seems that signals such as SIGPIPE, SIGINT, etc will still
kill the process. I also tried replacing the pthread_sigmask call with
sigprocmask to see if it made any difference, which it didn't.

The only other relevant info I can think of, is that I start up another
thread specifically for catching SIGTERM, thusly:

(void)sigemptyset(&signalSet);
(void)sigaddset(&signalSet, SIGTERM);
if (sigwait(&signalSet, &signo) < 0 || signo != SIGTERM)
/* some error handling */;

/* shutdown cleanly */
etc.

This part still works as expected.

Additionally, I have the same code working under Solaris threads (not pthreads
on Solaris) fine, the only relevant change being the call thr_sigsetmask
instead of pthread_sigmask.

The same behaviour is exhibited on 4.3-RELEASE and 4.4-RELEASE.

Any ideas on what is wrong?

regards,
Callum

(c)2002 Callum Gibson callum...@db.com
Global Markets IT, Deutsche Bank, Australia 61 2 9258 1620
### The opinions in this message are mine and not Deutsche's ###

To Unsubscribe: send mail to majo...@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message

Daniel Eischen

unread,
Feb 4, 2002, 10:42:41 PM2/4/02
to callum...@db.com, hac...@freebsd.org
On Tue, 5 Feb 2002 callum...@db.com wrote:
> Hi all,
> I have an application which attempts to block all signals using
> pthread_sigmask(). I'm aware that this only works on the current thread,
> however this call occurs before any other threads are created and so
> should be inherited. I call it as follows:
>
> sigset_t signalSet;
>
> (void)sigfillset(&signalSet);
> (void)pthread_sigmask(SIG_BLOCK, &signalSet, NULL);
>
> However, it seems that signals such as SIGPIPE, SIGINT, etc will still
> kill the process. I also tried replacing the pthread_sigmask call with
> sigprocmask to see if it made any difference, which it didn't.

Yes, at least with FreeBSD pthreads you have to either install a signal
handler to catch these signals or to set the handler to SIG_IGN. When
you set a threads signal mask, even if it is for all threads, you don't
affect how signals are delivered to the process. The default action
for SIGPIPE and SIGINT is to kill the process, so setting masks for
threads doesn't affect this.

> The only other relevant info I can think of, is that I start up another
> thread specifically for catching SIGTERM, thusly:
>
> (void)sigemptyset(&signalSet);
> (void)sigaddset(&signalSet, SIGTERM);
> if (sigwait(&signalSet, &signo) < 0 || signo != SIGTERM)
> /* some error handling */;
>
> /* shutdown cleanly */
> etc.
>
> This part still works as expected.

POSIX explicitly states that if you use sigwait() and there are no
handlers installed, that the effect is as if a handler is installed
for the signal. So using sigwait() will automagically install a
handler for the signal and then remove it once the sigwait() is
completed (that is, unless the application already installed a handler
for the signal, in which case sigwait doesn't install a handler).

--
Dan Eischen

callum...@db.com

unread,
Feb 4, 2002, 11:02:37 PM2/4/02
to eis...@pcnet1.pcnet.com, hac...@freebsd.org
Thanks, Dan. (I saw your name come up in the archives next to a lot of
threads/signals posts while I was looking for an answer to this so I
wondered if you'd answer. :-)

eis...@pcnet1.pcnet.com writes:
}> However, it seems that signals such as SIGPIPE, SIGINT, etc will still
}> kill the process. I also tried replacing the pthread_sigmask call with
}> sigprocmask to see if it made any difference, which it didn't.
}Yes, at least with FreeBSD pthreads you have to either install a signal
}handler to catch these signals or to set the handler to SIG_IGN. When
}you set a threads signal mask, even if it is for all threads, you don't
}affect how signals are delivered to the process. The default action
}for SIGPIPE and SIGINT is to kill the process, so setting masks for
}threads doesn't affect this.

I figured it was just using the default action for these signals. So, am
I mistaken in thinking that SIG_BLOCK was supposed to ignore those signals
or is this a pthreads bug on FreeBSD? Or just an "undefined" behaviour
and a pthreads gotcha? It's worth noting that even with pthreads on Solaris
I get the behaviour I was expecting (ie the signals are ignored) using
either pthread_sigmask or sigprocmask.

Also, is it documented anywhere which signals will behave like this? It
seems like it would be all of them, as if the process still has an inherent
signal mask independent of the threads running, thus requiring signal
handlers to be installed for them. Hmm, it's a lot more verbose calling
sigaction for every signal rather than a single pthread_sigmask call.
I guess that's why we have for loops.

C

(c)2002 Callum Gibson callum...@db.com
Global Markets IT, Deutsche Bank, Australia 61 2 9258 1620
### The opinions in this message are mine and not Deutsche's ###

To Unsubscribe: send mail to majo...@FreeBSD.org

callum...@db.com

unread,
Feb 4, 2002, 11:31:13 PM2/4/02
to hac...@freebsd.org, eis...@pcnet1.pcnet.com
callum writes:
}handlers to be installed for them. Hmm, it's a lot more verbose calling
}sigaction for every signal rather than a single pthread_sigmask call.
}I guess that's why we have for loops.

Doh! You can specify a set of signals with sigaction. Sorry about that.

Daniel Eischen

unread,
Feb 5, 2002, 12:27:03 AM2/5/02
to callum...@db.com, hac...@freebsd.org
On Tue, 5 Feb 2002 callum...@db.com wrote:
> Thanks, Dan. (I saw your name come up in the archives next to a lot of
> threads/signals posts while I was looking for an answer to this so I
> wondered if you'd answer. :-)
>
> eis...@pcnet1.pcnet.com writes:
> }> However, it seems that signals such as SIGPIPE, SIGINT, etc will still
> }> kill the process. I also tried replacing the pthread_sigmask call with
> }> sigprocmask to see if it made any difference, which it didn't.
> }Yes, at least with FreeBSD pthreads you have to either install a signal
> }handler to catch these signals or to set the handler to SIG_IGN. When
> }you set a threads signal mask, even if it is for all threads, you don't
> }affect how signals are delivered to the process. The default action
> }for SIGPIPE and SIGINT is to kill the process, so setting masks for
> }threads doesn't affect this.
>
> I figured it was just using the default action for these signals. So, am
> I mistaken in thinking that SIG_BLOCK was supposed to ignore those signals
> or is this a pthreads bug on FreeBSD? Or just an "undefined" behaviour
> and a pthreads gotcha? It's worth noting that even with pthreads on Solaris
> I get the behaviour I was expecting (ie the signals are ignored) using
> either pthread_sigmask or sigprocmask.

It's not clear to me that using pthread_sigmask should change
the default behaviour that signals have on the process. Thread
signal masks seem to be independent of installed signal handlers
and default actions that signals have on the process.

> Also, is it documented anywhere which signals will behave like this? It
> seems like it would be all of them, as if the process still has an inherent
> signal mask independent of the threads running, thus requiring signal
> handlers to be installed for them. Hmm, it's a lot more verbose calling
> sigaction for every signal rather than a single pthread_sigmask call.
> I guess that's why we have for loops.

See sigaction(2).

From your other email:

> Doh! You can specify a set of signals with sigaction. Sorry about that.

Nope, you can only install a handler for one signal at a time.

--
Dan Eischen

callum...@db.com

unread,
Feb 5, 2002, 12:48:51 AM2/5/02
to eis...@pcnet1.pcnet.com, hac...@freebsd.org
Let me know if I should take this off list now since it's probably reached
its limit of interest for most people.

eis...@pcnet1.pcnet.com writes:
}> I figured it was just using the default action for these signals. So, am
}> I mistaken in thinking that SIG_BLOCK was supposed to ignore those signals
}> or is this a pthreads bug on FreeBSD? Or just an "undefined" behaviour
}> and a pthreads gotcha? It's worth noting that even with pthreads on Solaris
}> I get the behaviour I was expecting (ie the signals are ignored) using
}> either pthread_sigmask or sigprocmask.
}It's not clear to me that using pthread_sigmask should change
}the default behaviour that signals have on the process. Thread
}signal masks seem to be independent of installed signal handlers
}and default actions that signals have on the process.

Well, it depends on what it means to block a signal. From reading the manpage
it seems to indicate that delivery of these signals is deferred indefinitely
until a thread sigwaits for them or if a thread doesn't have them blocked.
Since I was doing this as the very first thing in the process (ie there
are no other threads), it would imply that all other threads created from
then on would also block those signals. This is certainly how it behaves on
Solaris. Haven't checked Linux but will report back if you're interested.
In practice, FreeBSD's thread library probably has internal threads operating
in the background which are there from the outset and don't inherit this
mask and it's _those_ threads which are taking delivery of the fatal signals.

}> Also, is it documented anywhere which signals will behave like this? It
}> seems like it would be all of them, as if the process still has an inherent
}> signal mask independent of the threads running, thus requiring signal
}> handlers to be installed for them. Hmm, it's a lot more verbose calling
}> sigaction for every signal rather than a single pthread_sigmask call.
}> I guess that's why we have for loops.
}See sigaction(2).

Yeah, doesn't really explain if the process is anything more than the
sum of its threads. Under Solaris that's all it is. A non-threaded process
is actually a process with a single thread. This is the state of the process
when I do the sigprocmask/thr_setsigmask/pthread_sigmask call. It's only
after you make your first call to the thread library proper (by creating
a new thread) that the background threads appear (this is on Solaris).
I suspect this is not how it works on FreeBSD - the method of compilation
even gives a clue to this (a special compiler directive). Even without making
any new threads a FreeBSD threaded program will probably have these internal
threads (I'm speculating here as I don't have the equivalent of pstack
to be able to check that). I guess it also has something to do with being
a userland implementation?

I guess the question boils down to: Should an application be able to operate
oblivious to the existence of internal threads? Does a process exist
apart from the threads that make it up?

Anyway, sigaction does the trick - it just seems superfluous on Solaris,
at least.

}>From your other email:
}> Doh! You can specify a set of signals with sigaction. Sorry about that.
}Nope, you can only install a handler for one signal at a time.

Spotted that just after I sent it but I figured replying to myself twice
in a row was Really Bad (tm). I was right the first time.

C

(c)2002 Callum Gibson callum...@db.com
Global Markets IT, Deutsche Bank, Australia 61 2 9258 1620
### The opinions in this message are mine and not Deutsche's ###

To Unsubscribe: send mail to majo...@FreeBSD.org

0 new messages