The signal is delivered to a particular thread, so the signal handler runs in a particular thread (the thread the signal was delivered to). If the signal is delivered to a thread writing out 222\n then that thread must stop writing out 222\n and run the signal handler. Your example signal handler takes a full second to run, so that's a full second during which that thread may not write out 222\n.
The signal is delivered to a particular thread, so the signal handler runs in a particular thread (the thread the signal was delivered to). If the signal is delivered to a thread writing out 222\n, then that thread must stop writing out 222\n and run the signal handler. Your example signal handler takes a full second to run, so that's a full second during which that thread may not write out 222\n.
Additionally, since you are using printf to write out all of these bytes, there is some locking being done in libc. Since printf is not an "async signal safe" function, it's actually undefined what happens if you use it in a signal handler. One possible explanation for the behavior you observe is this.
If the signal is delivered to a thread while that thread holds the stdout lock, then no other thread will be able to write to stdout until the handler returns and the lock can be released by the "normal" code running in that thread. The signal handler can still write to stdout in this case, though, because the lock is an rlock which can be acquired repeatedly any particular thread. This may vary from depending on the specific platform, C library, thread library, or phase of the moon, though.
Your example is easily converted to use write(2) though, which demonstrates more or less the same problem behavior, has more or less the same fix, and doesn't rely on undefined behavior. If you SIG_BLOCK the timer signal in the 222\n threads, then the signal handler will always run in the main thread and you will continue to get 222\n output while the signal handler sleeps. Seth also makes a great point about only using the safe functions in signal handlers.
Using any others means your program's behavior is undefined.
The fact that stdio locking is recursive does not mean it will work from a signal handler when the lock is already held in the calling thread. Recursive is a much weaker requirement than reentrant, and in fact neither stdio nor the locking it uses is usually reentrant. – R.. May 25 at 20:25 Thanks, great point.
I've edited the answer to make it clear that the printf behaviors are undefined in this case, and pointed out an alternative which is somewhat equivalent, but which avoids undefined behavior. – Jean-Paul Calderone May 25 at 20:31 The observed behaviour is actually due to printf's lock. Changing printf to write, you get the saner behaviour that the children are writing 222 and occasionally 000, 111 until all three threads end up sleeping on the signal handler (with further signals blocked) and no longer write 222.
– ninjalj May 25 at 20:51.
Often times, signals (or at least that signal) is blocked when you are in a signal handler. It is also a bad idea to do very much in a signal handler. Generally you should set a variable or something like that, and then deal with the signal once you are in your normal codepath.
See sigaction's SA_NODEFER flag for a way to permit or deny receiving a signal inside a signal handler. There is also a limited number of functions which are safe to call from inside a signal handler. Signal(7) man page describes this."A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program.
POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined" A program which calls an unsafe function from inside a signal handler is broken. On some machines it will "work"; on others it will coredump.
It is permitted to do anything or nothing, including reformatting the disk, subjecting the user to scratchy Barry Manilow records played backwards, or dropping a tacnuke on Dallas. Attempting to call an unsafe function puts the program into the twilight zone of undefined behavior. With apologies to der Mouse.
Calling an unsafe function from a signal handler is sometimes valid, if you can guarantee that it did not interrupt an unsafe function. For example if the thread is just executing for (;;) pause(); then you can do whatever you want in the signal handler. – R.. May 25 at 20:27 If only I had said that.
Oh wait! I did! – Seth Robertson May 25 at 20:39 I was replying to this sentence: "A program which calls an unsafe function from inside a signal handler is broken." which is an oversimplification.
Most naively written programs which do so are broken, but it's due to the programmer making an error not checking what other functions might be interrupted, not an inherent result of using async-signal-unsafe functions in a signal handler. – R.. May 25 at 20:48.
The signal is delivered to a particular thread, so the signal handler runs in a particular thread (the thread the signal was delivered to). If the signal is delivered to a thread writing out 222\n then that thread must stop writing out 222\n and run the signal handler. Your example signal handler takes a full second to run, so that's a full second during which that thread may not write out 222\n .
Often times, signals (or at least that signal) is blocked when you are in a signal handler. It is also a bad idea to do very much in a signal handler. Generally you should set a variable or something like that, and then deal with the signal once you are in your normal codepath.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.