Re: SIGPIPE and SIG_IGN
Re: SIGPIPE and SIG_IGN
- Subject: Re: SIGPIPE and SIG_IGN
- From: Terry Lambert <email@hidden>
- Date: Tue, 19 Jun 2007 03:35:51 -0700
On Jun 18, 2007, at 6:10 PM, Glenn Anderson wrote:
At 5:30 pm -0700 18/6/2007, Terry Lambert wrote:
This also means that the signal will not get sent if you are
ignoring it, and it's in your process signal mask (sigaction() is
generally preferred to calling signal(), but either should work).
Near the end of signal.h there is this:
/*
* signals delivered on a per-thread basis.
*/
#define threadmask (sigmask(SIGILL)|sigmask(SIGTRAP)|\
sigmask(SIGIOT)|sigmask(SIGEMT)|\
sigmask(SIGFPE)|sigmask(SIGBUS)|\
sigmask(SIGSEGV)|sigmask(SIGSYS)|\
sigmask(SIGPIPE))
Is this not true?
It is has been my experience that if you want to ignore SIGPIPE, you
have to ignore it on every thread that could trigger it (ie: call
signal(SIGPIPE, SIG_IGN) on every thread that writes to sockets that
could close), you can't just ignore it for the whole process.
I pretty much rewrote all of the signal handling code in the kernel
for UNIX conformance for Leopard, so I'm rather familiar with the code
here for both Tiger and Leopard. 8-).
-
The threadmask is only consulted when threadsignal() is called, which
only happens in catch_exception_raise(), and in proc_exit() or
vproc_exit() when the process is exiting and may need to signal a
specific thread in a sigwait().
Neither of these happen for a SIGPIPE.
The catch_exception_raise() only happens when you raise an exception
on an exception port as a result of sending a Mach message, usually
from user space, usually as a result of a C++ exception being thrown.
-
There are two levels of masking, one for threads, and one for the
process. If you set the process mask, the signal is not delivers to
the process, period. You can also block the delivery via sigblock()
(but it gets pended, so when it's unblocked, it will get delivered).
If the signal is masked on a thread but not on a process, then it will
get delivered to any thread in the process except the thread(s) that
masked it. This happens in the BSD AST handling code when any given
thread that does not have the signal masked runs up to the user/kernel
boundary, which triggers the trampoline code to run in user space to
fire the signal handler on that thread (it does this by returning to
an address offset from the intended system call return address). The
user space signal handler fires, and, on completion calls
__sigreturn() to throw it back into the kernel to complete the call
that you were trampolined from, and return to user space.
-
The main issue that people tend to miss when they mix threads and
signals is that all of the standard POSIX (and BSD) interfaces are
process-wide _and MUST be_, since they predate the concept of pthreads.
The only way to deal with threads issues directly is to use the
threads APIs AFTER using the standard historical APIs; specifically,
you want to mask the signals using the API:
sigprocmask()
And you want to deal with the thread masking to mask it for all
threads via pthread_sigmask() on a thread-by-thread basis; there's
sample code that gives a (really: don't use it directly) abbreviated
example here:
<http://www.opengroup.org/onlinepubs/009695399/functions/pthread_sigmask.html
>
But I *HIGHLY* recommend the tutorial in the O'Reilly pthreads book.
--
From the description, without a cut down test case and a bug filing
including the test case, we can't really help you further, other than
to point you at documentation. What you have described seeing should
not be happening, (and doesn't according standards-based testing).
What is most likely happening is that you have a library or a class,
template, etc., which is either creating a thread behind your back, or
is messing around with the signal mask for the thread and/or process.
Note that the standard template library *will* create threads on your
behalf when you utilize some templates, so that could be your culprit.
In general, the most appropriate approach is to designate a signal
thread by storing it's pointer off, and if you get the signal on a
thread other than the signal thread (pthread_self() doesn't match the
catcher thread's ID), then re-throw it to the correct thread using
pthread_kill().
In the case that you are attempting to ignore a signal entirely, you
need to make sure no one else is messing with your process/thread
signal mask behind your back.
Anything more *REALLY* needs a cut-down test case and a bug filed.
-- Terry
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden