|
Home > Archive > Unix Programming > January 2005 > pthread_cond_signal in a signal handler?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
pthread_cond_signal in a signal handler?
|
|
| red floyd 2004-06-26, 10:10 am |
|
is it safe to call pthread_cond_signal() from within a signal handler
(specifically SIGALRM)?
I'm trying to implement a generic timer queue using itimers, and to
avoid doing a ton of work inside the signal handler, I'd like to have a
thread waiting on a condition variable, and signal it when the itimer
goes off.
TIA
| |
| Måns Rullgård 2004-06-26, 10:10 am |
| red floyd <no.spam@here.dude> writes:
> is it safe to call pthread_cond_signal() from within a signal handler
> (specifically SIGALRM)?
No, but sem_post() is OK. Maybe you can use it instead.
--
Måns Rullgård
mru@kth.se
| |
| Joe Seigh 2004-06-26, 10:10 am |
|
red floyd wrote:
>
> is it safe to call pthread_cond_signal() from within a signal handler
> (specifically SIGALRM)?
>
> I'm trying to implement a generic timer queue using itimers, and to
> avoid doing a ton of work inside the signal handler, I'd like to have a
> thread waiting on a condition variable, and signal it when the itimer
> goes off.
>
You could but if you use locks to avoid risking a race condition and
missing the condvar signal, you could get deadlocked. Use a semaphore
as another poster has suggested.
If you could guarantee that the thread receiving the signal didn't use
the locks, you might be able to get away with using locks in the signal
handler. It's sort of iffy as most of pthreads is not async signal safe.
Joe Seigh
| |
| Joe Seigh 2004-06-26, 10:10 am |
|
Forget pthread_cond_signal. I just remembered what the NPTL futex condvars look like.
Just because I can implement a lock-free condvar doesn't mean others are likely to do that.
Stick to a semaphore or sigwaitinfo() or sigtimedwait().
Joe Seigh
| |
| red floyd 2004-06-26, 10:10 am |
| Joe Seigh wrote:
>
> Forget pthread_cond_signal. I just remembered what the NPTL futex condvars look like.
> Just because I can implement a lock-free condvar doesn't mean others are likely to do that.
> Stick to a semaphore or sigwaitinfo() or sigtimedwait().
>
> Joe Seigh
Is sigtimedwait()/sigwaitinfo() really a solution? The man page I have
for that (from MDK9.1) says "sigwaitinfo() suspends execution of the
calling process"
I know that in some cases, a thread is a new process (created by
clone()), but in a system where a thread is *not* a process, wouldn't
that block the entire process rather than the calling thread?
Looks like I'm going to have to look into POSIX sems.
| |
| Joe Seigh 2004-06-26, 10:10 am |
|
red floyd wrote:
> Is sigtimedwait()/sigwaitinfo() really a solution? The man page I have
> for that (from MDK9.1) says "sigwaitinfo() suspends execution of the
> calling process"
>
> I know that in some cases, a thread is a new process (created by
> clone()), but in a system where a thread is *not* a process, wouldn't
> that block the entire process rather than the calling thread?
>
> Looks like I'm going to have to look into POSIX sems.
http://www.opengroup.org/onlinepubs...igwaitinfo.html
Threads as far as I know.
Joe Seigh
| |
| red floyd 2004-06-26, 10:10 am |
| Joe Seigh wrote:
>
> red floyd wrote:
>
>
>
> http://www.opengroup.org/onlinepubs...igwaitinfo.html
>
> Threads as far as I know.
>
> Joe Seigh
Thanks, Joe. Stevens UNP vol 2 2ed discusses sigwait/sigwaitinfo in a
threaded environment. Should have dragged that one out to begin with.
| |
| red floyd 2004-06-26, 10:10 am |
| Joe Seigh wrote:
>
> Forget pthread_cond_signal. I just remembered what the NPTL futex condvars look like.
> Just because I can implement a lock-free condvar doesn't mean others are likely to do that.
> Stick to a semaphore or sigwaitinfo() or sigtimedwait().
>
> Joe Seigh
So my timer queue logic should probably look like this?
PSEUDOCODE:
timer_q_thread()
{
while (program_running)
{
while (!sigalrm_occured)
sigwait(); // yeah a param, but this is pseudocode
pthread_sigmask(SIG_BLOCK, SIGALRM); // yeah, sigset_t
sigalrm_occured = 0;
process_timer();
pthread_sigmask(SIG_UNBLOCK, SIGALRM);
}
}
void sigalrm_hdlr(int sig)
{
sigalrm_occurred = 1;
}
| |
| Joe Seigh 2004-06-26, 10:10 am |
|
red floyd wrote:
>
> So my timer queue logic should probably look like this?
>
> PSEUDOCODE:
>
> timer_q_thread()
> {
> while (program_running)
> {
> while (!sigalrm_occured)
> sigwait(); // yeah a param, but this is pseudocode
> pthread_sigmask(SIG_BLOCK, SIGALRM); // yeah, sigset_t
> sigalrm_occured = 0;
> process_timer();
> pthread_sigmask(SIG_UNBLOCK, SIGALRM);
> }
> }
>
> void sigalrm_hdlr(int sig)
> {
> sigalrm_occurred = 1;
> }
You don't need a signal handler defined w/ sigaction. I think there was
a bug in Solaris that required sigaction w/ signal handler set to NULL.
You should do a sighold on the signal to keep it from getting deliverd
with the default action (process dies). sigwaitinfo will get it anyway.
Might be easier to do a timer queue with pthread_cond_timedwait. You can
do pthread_condattr_setclock if you have it and need to use the other
clock types. And it's likely to be more efficient and have less latency
than a signal based delivery mechanism. And a lot less problematic.
Joe Seigh
| |
| red floyd 2004-06-26, 10:10 am |
| Joe Seigh wrote:
>
> red floyd wrote:
>
>
>
>
> You don't need a signal handler defined w/ sigaction. I think there was
> a bug in Solaris that required sigaction w/ signal handler set to NULL.
> You should do a sighold on the signal to keep it from getting deliverd
> with the default action (process dies). sigwaitinfo will get it anyway.
>
> Might be easier to do a timer queue with pthread_cond_timedwait. You can
> do pthread_condattr_setclock if you have it and need to use the other
> clock types. And it's likely to be more efficient and have less latency
> than a signal based delivery mechanism. And a lot less problematic.
>
> Joe Seigh
Joe,
Once again, thanks. I'm kind of new to pthreads programming, so I'm not
familiar with all the things that could be done... I'll check
pthread_cond_timedwait.
| |
| Patrick TJ McPhee 2004-06-26, 10:10 am |
| In article <4sEBc.6701$86.1551@newssvr27.news.prodigy.com>,
red floyd <no.spam@here.dude> wrote:
% I'm trying to implement a generic timer queue using itimers, and to
% avoid doing a ton of work inside the signal handler, I'd like to have a
% thread waiting on a condition variable, and signal it when the itimer
% goes off.
Leaving pthread_cond_signal aside, you need to lock a mutex, update a
predicate, and unlock the mutex if you want to get the semantics of
the condition wait right, and you can't do any of that in a signal
handler.
On the other hand, you could set up a dedicated timer thread and have
it block on pthread_cond_timedwait.
--
Patrick TJ McPhee
East York Canada
ptjm@interlog.com
| |
| nobody 2004-06-26, 10:10 am |
| "red floyd" <no.spam@here.dude> wrote in message
news:5LMBc.7293$ja4.3064@newssvr27.news.prodigy.com...
> Joe Seigh wrote:
can[vbcol=seagreen]
>
> Joe,
>
> Once again, thanks. I'm kind of new to pthreads programming, so I'm not
> familiar with all the things that could be done... I'll check
> pthread_cond_timedwait.
>
Then maybe you want to have a look at
http://docs.sun.com/db/doc/806-5257
I know it's Sun, but can give you some insight.
Chapter 6 describes async-signal-safe functions.
Don't have more time right now to look, but either in this publication,
or some other (on same site) is also some treatment for signal
handling in MT env. Idea is to have dedicated one thread to async signal
handling, and block (async) signal delivery in all other threads (see signal
mask inheritance by spawned threads). Worked for me, but as always,
"the devil is in the details". Had some deadlock situation (regarding to
waiting
for condition, as some other post seems to be suggesting) and wasn't given
an opprtunity to fix it (company's policy for graceful shutdown: kill -9)..
I've always wondered about doors.
| |
| Sean Burke 2004-06-26, 10:11 am |
|
ptjm@interlog.com (Patrick TJ McPhee) writes:
> In article <4sEBc.6701$86.1551@newssvr27.news.prodigy.com>,
> red floyd <no.spam@here.dude> wrote:
>
> % I'm trying to implement a generic timer queue using itimers, and to
> % avoid doing a ton of work inside the signal handler, I'd like to have a
> % thread waiting on a condition variable, and signal it when the itimer
> % goes off.
>
> Leaving pthread_cond_signal aside, you need to lock a mutex, update a
> predicate, and unlock the mutex if you want to get the semantics of
> the condition wait right, and you can't do any of that in a signal
> handler.
>
> On the other hand, you could set up a dedicated timer thread and have
> it block on pthread_cond_timedwait.
I have an implementation of this method (dedicated timer thread blocking
on pthread_cond_timedwait()) that you are free to use.
Look in
ftp://ftp.xenadyne.com/Nifty.tgz
at nft_task.c.
-SEan
| |
|
|
|
|
|
|
| Sean Burke 2005-01-14, 5:52 pm |
|
red floyd <no.spam@here.dude> writes:
> Sean Burke wrote:
>
> Sean and Joe: could you take a look at
> http://alumni.cse.ucsc.edu/~scottn/timerthread.cpp and see if you can
> see anything obviously wrong? My embedded q&d test case seems to work
> properly.
>
> I'd really appreciate it.
Looks good to me, although I didn't see where you free the Timer instances,
unless timer_queue.pop() does this. Also, you might consider whether you want
to spawn a new thread to execute each timer instance. You could call the
task function inline, and that function could call create_thread() or not,
depending whether the function is going to perform a lengthy task.
-SEan
|
|
|
|
|