|
Home > Archive > Unix Programming > April 2006 > sigwait() Questions
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 |
sigwait() Questions
|
|
| Josh Birnbaum 2006-03-16, 7:51 am |
| Hi Folks,
I have some questions regarding some POSIX timers code that I've
written that makes use of sigwait().
As can be seen below, I block SIGINT, set up a timer and then drop
into an infinite loop where sigwait() blocks until my timer expires
and generates SIGINT.
Firstly, is it enough for me to block SIGINT in the calling thread
as I do here? And do I need to re-block once I enter the loop that
contains sigwait()?
Secondly, sigwait() does not like it if I define sig as volatile. I
would like to do this for reasons of atomicity. Is there an altern-
ative to this?
The code follows. Any feedback re the above is welcome.
Thanks,
Josh.
/*** timer.c ***/
#include "timer.h"
static sigset_t newMask;
static sigset_t oldMask;
int main()
{
struct sigevent evpTimerOne;
struct itimerspec spec;
timer_t timerOne = 0;
int sig = 0;
sigemptyset( &newMask );
sigaddset( &newMask, SIGINT );
sigprocmask( SIG_BLOCK, &newMask, &oldMask );
evpTimerOne.sigev_notify = SIGEV_SIGNAL;
evpTimerOne.sigev_signo = SIGINT;
if( timer_create( CLOCK_REALTIME, &evpTimerOne, &timerOne ) != 0 )
{
perror( "timer: ERROR: timer_create" );
exit( EXIT_FAILURE );
}
spec.it_value.tv_sec = 3;
spec.it_value.tv_nsec = 0;
spec.it_interval.tv_sec = 3;
spec.it_interval.tv_nsec = 0;
if( timer_settime( timerOne, 0, &spec, NULL ) != 0 )
{
perror( "timer: ERROR: timer_settime" );
exit( EXIT_FAILURE );
}
for( ;; )
{
sigwait( &newMask, &sig );
if( sig == SIGINT )
{
printf( "caught SIGINT\n" );
}
}
return (0);
}
/*** timer.h ***/
#ifndef TIMER_H
#define TIMER_H
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#endif /* TIMER_H */
| |
| Frank Cusack 2006-03-16, 7:51 am |
| On Thu, 16 Mar 2006 03:53:50 GMT Josh Birnbaum <engineer@noorg.org> wrote:
> Hi Folks,
>
> I have some questions regarding some POSIX timers code that I've
> written that makes use of sigwait().
> As can be seen below, I block SIGINT, set up a timer and then drop
> into an infinite loop where sigwait() blocks until my timer expires
> and generates SIGINT.
>
> Firstly, is it enough for me to block SIGINT in the calling thread
> as I do here?
As you do here, yes. But in a threaded program, no. If one thread has
a signal blocked, it can be posted to another thread. (Based on my
best reading of SUSv3, which says that timer_create() creates a
per-PROCESS timer.)
If the notification signal is per-process, you'll need to block SIGINT
in all threads, to guarantee that only your thread catches the signal.
If other threads do not have SIGINT blocked, and you reach sigwait()
before the signal is delivered, you'll still get the signal. But
there's no guarantee you'll reach the sigwait() call before the signal
is delivered.
If the notification signal is thread-directed, your code will work.
It's easy to test this.
> And do I need to re-block once I enter the loop that
> contains sigwait()?
no, it remains blocked.
> Secondly, sigwait() does not like it if I define sig as volatile. I
> would like to do this for reasons of atomicity. Is there an altern-
> ative to this?
Not sure why you'd need to do that. volatile doesn't do what you think
it does.
-frank
ps, if you are using Solaris, look at
http://developers.sun.com/solaris/a...completion.html
| |
| Josh Birnbaum 2006-03-19, 12:02 pm |
| Frank Cusack wrote:
Hi Frank,
> On Thu, 16 Mar 2006 03:53:50 GMT Josh Birnbaum <engineer@noorg.org> wrote:
>
> As you do here, yes. But in a threaded program, no.
Isn't my program a threaded program given its use of timer_create() and
timer_settime()?
> If one thread has a signal blocked, it can be posted to another thread.
> (Based on my best reading of SUSv3, which says that timer_create()
> creates a per-PROCESS timer.)
>
> If the notification signal is per-process, you'll need to block SIGINT
> in all threads, to guarantee that only your thread catches the signal.
> If other threads do not have SIGINT blocked, and you reach sigwait()
> before the signal is delivered, you'll still get the signal. But
> there's no guarantee you'll reach the sigwait() call before the signal
> is delivered.
Is it not the case now that I block across all threads by blocking
SIGINT
by calling sigprocmask() early in my code? This is predicated on part of
my additional research into this that suggests that new threads inherit
the signal mask of their creator. The "creator" thread is the only one
in existance at program startup and it calls sigprocmask() early in
main().
> If the notification signal is thread-directed, your code will work.
Thread directed as opposed to process directed?
> It's easy to test this.
How would I do this?
>
> no, it remains blocked.
Good. That answers an important question.
>
> Not sure why you'd need to do that. volatile doesn't do what you think
> it does.
As I understand it, a variable prefixed with the volatile keyword tells
the compiler that it should not make any assumptions (via optimization)
about the variables value.
Given it's use in my endless sigwait() for(;;) loop, I wanted my
references
to the volatile variable value therein to be totally accurate.
It seems though that I don't need to do this here, given your feedback.
> -frank
> ps, if you are using Solaris, look at
> http://developers.sun.com/solaris/a...completion.html
Not yet. But I will be developing under Solaris in time.
Thanks alot for your feedback Frank.
Yours,
Josh.
| |
| Frank Cusack 2006-03-21, 3:17 am |
| On Sun, 19 Mar 2006 05:37:17 GMT Josh Birnbaum <engineer@noorg.org> wrote:
> Frank Cusack wrote:
>
> Hi Frank,
>
>
> Isn't my program a threaded program given its use of timer_create() and
> timer_settime()?
Not at all! Yes, it does give you an asynchronous notification, but
there isn't some hidden thread that runs. What would that thread be
doing?
What happens (give or take) is that during normal kernel scheduler
processing, it checks to see if your timer has expired and if so,
posts a signal to your process. Note that you used SIGEV_SIGNAL, not
SIGEV_THREAD (or SIGEV_PORT on Solaris). Had you used SIGEV_THREAD,
*then* your program would be multithreaded, however your sigwait()
wouldn't work ...
timer_create() (when using SIGEV_SIGNAL) is similar to alarm(). Would
you expect that alarm() makes your process multithreaded?
>
> Is it not the case now that I block across all threads by blocking
> SIGINT
> by calling sigprocmask() early in my code? This is predicated on part of
> my additional research into this that suggests that new threads inherit
> the signal mask of their creator. The "creator" thread is the only one
> in existance at program startup and it calls sigprocmask() early in
> main().
That only applies if you had used SIGEV_THREAD. Although, I wonder
what SUS has to say about the signal mask ... the thread calling
timer_create() isn't really the same as the thread creating the
notification thread. And what if you change the mask after calling
timer_create() but before the notification thread is created? And what
if the thread calling timer_create() goes away before the notification
thread is created?
When I say "I wonder", I mean, I can't find answers for this.
>
> Thread directed as opposed to process directed?
yes.
>
> How would I do this?
You'd create another thread with SIGINT unblocked. Do the timer stuff
in the thread that does have SIGINT blocked, but don't do sigwait()
(busy-wait instead). When the timer goes off, if it goes to the
thread that is busy-waiting, it's thread-directed. If it goes to
the other thread, it's process-directed.
I wouldn't count on such behavior being consistent across platforms or
even different versions of the same platform, though.
>
> As I understand it, a variable prefixed with the volatile keyword tells
> the compiler that it should not make any assumptions (via optimization)
> about the variables value.
> Given it's use in my endless sigwait() for(;;) loop, I wanted my
> references
> to the volatile variable value therein to be totally accurate.
> It seems though that I don't need to do this here, given your feedback.
Yes, it can't possibly be the case that you run into a problem there,
and volatile will do nothing. I am surprised that if fails to compile
at all though.
-frank
| |
| Josh Birnbaum 2006-04-02, 7:42 pm |
| Josh Birnbaum wrote:
>
> Frank Cusack wrote:
>
Hi Frank,
Many thanks for your shedding some light on all of this. Its clarified
alot.
Yours,
Josh.
| |
|
| Hi Frank,
We too have a similar peculiar problem. We are using real time
signals to handle timer expiry for timer_create() function. After the
system running for an hour or two, the process/thread is entering to
SIGSUSPEND state.
Any pointers to where we should dig up, will be helpful?
Thankx,
Sats
Josh Birnbaum wrote:
> Josh Birnbaum wrote:
>
> Hi Frank,
>
> Many thanks for your shedding some light on all of this. Its clarified
> alot.
>
> Yours,
>
> Josh.
|
|
|
|
|