Benubird
Benubird

Reputation: 19487

Race condition in C signal handlers puzzle

I need to know how to avoid a race condition when handling signals in C. Each time my program receives a signal, I want it to alter a (global) linked list. It is vitally important that I not miss a signal, and equally important that the global linked list I'm modifying not be changed while the handler is executing.

The problem is, if I receive a signal, and start the handler, but am then interrupted by another signal. This (as I understand it) triggers a new execution of the signal handler, which will operate on the same global dataset - not permissible!

I can't use a lock, because if the first handler call is interrupted, it will naturally never free the lock for the interrupting handler to pick up. So, how do I do it? Any idea?

Upvotes: 6

Views: 1382

Answers (4)

Nate
Nate

Reputation: 12829

If you have the luck to be working in a multi-threaded environment, one of the best ways is to have the global linked list controlled exclusively by a separate thread. Interrupts would enqueue requests to this thread (something that would be executed very quickly, say, by simply passing a pointer), and then the thread would procedurally go through each request and modify the linked list. This allows lockless execution.

Of course, you have to rely on your OS's message passing junk, so that may not be an option.

Upvotes: 1

Sim Sun
Sim Sun

Reputation: 587

I think you should seriate the signal.just like the work queue E.g. all the signal should put into a work queue(FIFO), and then the executing thread poll the queue all the time. if the queue is not empty,this thread will pick the top signal and start it`s handler. keep doing like that, until the queue is empty.

Upvotes: 0

jcomeau_ictx
jcomeau_ictx

Reputation: 38432

From http://users.evtek.fi/~tk/rtp/signals-programming.html:

The way to guarantee no races at all, is to let the system set the signal masking for us before it calls the signal handler. This can be done if we use the sigaction() system call to define both the signal handler function AND the signal mask to be used when the handler is executed. You would probably be able to read the manual page for sigaction() on your own, now that you're familiar with the various concepts of signal handling. On old systems, however, you won't find this system call, but you still might find the sigvec() call, that enables a similar functionality.

Upvotes: 1

qrdl
qrdl

Reputation: 34968

You can mask signals while executing signal handler - check sa_mask field of struct sigaction you pass to sigaction() syscall.

Upvotes: 1

Related Questions