tags:

views:

256

answers:

5

Hello all, I'm using a real time signal in Linux to be notified of the arrival of new data in a serial port. Unfortunately this causes sleep calls to be interrupted when there is signal. Does anybody know of a way to avoid this behavior.

Edit: I tried using a regular signal (SIGUSR1) but I keep getting the same behavior.

Thanks, Joao

+1  A: 

If you don't want to be interrupted, why are you using the real time signal?

Somewhere, either in Rockind's "Advanced Unix Programming" or Steven's book, there was an example of how to fake this out. You make note of the current time_t before starting your sleep. After the sleep ends, you check to make sure the required amount of time has elapsed, and if it hasn't, you start a new sleep. Put the sleep in a loop that calculates the time to go and sleeps that amount, and exits when the required time has passed.

Paul Tomblin
+4  A: 

You can mask almost all signals (except SIGKILL) using sigprocmask() or signal() calls. The first one will return you the previous mask, which you can recover after sleep(). Some examples are here. If that does not help, please, be more verbose of what signal interrupts your sleep. I think, you can additionally check this condition ("sleep interrupted by signal?") and fall into sleep again.

dma_k
+1  A: 

Well, a realtime signal is supposed to interrupt sleep. You could use a non-realtime signal instead. Another approach is to check if the expected time to sleep has elapsed, and if not, sleep for the remaining interval.

wallyk
Thanks for your answer, but using a regular signal also interrupts sleep calls.
jassuncao
+8  A: 

From the nanosleep manpage:

nanosleep delays the execution of the program for at least the time specified in *req. The function can return earlier if a signal has been delivered to the process. In this case, it returns -1, sets errno to EINTR, and writes the remaining time into the structure pointed to by rem unless rem is NULL. The value of *rem can then be used to call nanosleep again and complete the specified pause.

Martijn
I will go with this one. I gave a look inside the POCO libraries and their Thread::sleep implementation does something like you described.Thanks
jassuncao
Don't forget to check your selected answer.
Thomas Matthews
I won't but I prefer to wait a while before accepting an answer.
jassuncao
+2  A: 

Newer Linux kernels support signalfd(2). That, together with sigprocmask(2), is a very nice way to combine handling of signal and IO events in a single epoll_wait(2) call.

Nikolai N Fetissov