Reputation: 11
I am writing code on ucLinux for socket communication. I use select()
for reading the data on sockets. I also have a 20 msec timer (created using setitimer
) running in the same thread for performing a parallel operation. My select function gets blocked each time saying "Interrupted by system call", since it receives the SIGALRM signal issue by the timer on overflow, every 20 msec. I tried restarting the system when EINTR is issued, and run select()
again. but this wont help, since i will always receive the SIGALRM by timer every 20 msec. I dont want to ignore this signal since it is used for performing other tasks in the system, but i want to use select without being affected by this signal. Is there any way to handle this? I cannot use functions like timer_create()
as these are not supported on the platform I am using. So, I am stuck up with using setitimer
for timer creation. Is there any way I can run both together independently in my code?
Upvotes: 1
Views: 2449
Reputation: 1434
Is an option for you doing something like this?
While(1) {
int rc = select(nfds, &readfds, &writefds, &exceptfds, &timeout);
if ((rc < 0) && (errno == EINTR) )
continue;
else {
// some instructions
}
}
If this is not an option for you you can probably use pselect which adds a parameter to the end (sigmask) which specifies a set of signals that should be blocked during the pselect(), see here
Upvotes: 1
Reputation: 9685
What you're doing is pretty weird. Let's face it: timers are an ancient and mostly-obsolete mechanism for doing work. Pretty much everyone these days avoids signals like the plague. There's essentially nothing useful you can do in a signal callback (you certainly can't call anything complicated like malloc
for example), so you must have some way to get the timer notification back from the SIGALRM
handler to the main thread already -- you're not actually doing the work in the signal handler are you?
So you have two tactics: use the standard self-pipe trick to turn the signal into an event on an fd, the "normal" way to handle things like SIGTERM
, SIGINT
and so on. You call socketpair
or pipe
to make a pipe, then write a byte into the pipe from the signal handler. You read the byte back from you select
loop. You commonly write the value of the signal as the data, but you could write anything really.
The other tactic (much more sane) is to avoid the mess with signals and setitimer
completely. setitimer
is seriously legacy and causes problems for all sorts of things (eg. it can cause functions like getaddrinfo
to hang, a bug that still hasn't been fixed in glibc (http://www.cygwin.org/frysk/bugzilla/show_bug.cgi?id=15819). Signals are bad for your health. So the "normal" tactic is to use the timeout argument to select
. You have a linked list of timers, objects you use to manager periodic events in your code. When you call select
, you use as the timeout the shortest of your remaining timers. When the select
call returns, you check if any timers are expired and call the timer handler as well as the handlers for your fd events. That's a standard application event loop. This way your loop code so you can listen for timer-driven events as well as fd-driven events. Pretty much every application on your system uses some variant on this mechanism.
Upvotes: 4