Asynchronous signal security and thread security
Hedgehog @ http://blog.csdn.net/littlehedgehog
The problem arises from the introduction of thread security functions by Mr. Steven s in apue, who includes:If a function is reentrant to multiple threads, this function is thread-safe, but this does not mean it is also reentrant to the signal processing program. That is to say, the signal Security re-entry function requires stricter requirements than thread security.However, I want to know why the threads can all be reinjected, but the signal doesn't work?
Conjecture:
The internal implementation of standard library functions such as printf may have a mutex lock. This mutex lock is specially designed for the IO buffer, that is to say, the lock must be obtained before each logic execution stream is printed (printing means writing characters to the buffer zone), the content to be printed is input into the buffer zone, and the mutex lock is released.
Explanation:
To obtain mutex lock before printing, a deadlock may occur when printf is called in the signal processing program:The current logic execution stream calls printf. When the lock is obtained, the signal occurs. At this time, the execution stream has to call the signal processing function. Coincidentally, the signal processing function also needs to print printf, similarly, you need to obtain the buffer control lock, but the lock has been previously locked by yourself (this is your second lock deadlock phenomenon)So there is a deadlock. This can also be a good explanation of why the thread does not deadlock when calling printf, because even if a thread is adding a lock and thread switching occurs, the new thread needs to execute printf but finds that the buffer has been locked, wait for your sleep and no deadlock will occur. After the previous thread finishes printing, the lock will be released.
Proof:
The core of our above conjecture is that the standard buffer zone contains mutex locks. Each time the printf and other functions operate on the buffer zone, we only need to prove that this lock exists. You can directly look at the standard library code, but I write a program to prove this idea in an approximate way.
Multithreading: here we open up a thread, and then both the main thread and the secondary thread print a string to the screen with printf at the same time. Then we can check that if the string is completely printed every time, it is probably because the lock ensures that the print is complete each time and the string is not interrupted due to thread scheduling.
Void * thread_main (void * Arg) <br/>{< br/> sleep (5); <br/> (;;) <br/>{< br/> printf ("success"); <br/>}< br/> return NULL; <br/>}< br/> int thread_new (void * (* fN) (void *), void * Arg) <br/>{< br/> pthread_ttid; <br/> pthread_attr_tattr; <br/> pthread_attr_init (& ATTR); <br/> If (pthread_attr_setdetachstate (& ATTR, Pthread_create_detached )! = 0) <br/>{< br/> pthread_attr_destroy (& ATTR); <br/> return (-1 ); <br/>}< br/> If (pthread_create (& tid, & ATTR, FN, ARG )! = 0) <br/>{< br/> pthread_attr_destroy (& ATTR); <br/> return (-1 ); <br/>}< br/> pthread_attr_destroy (& ATTR); <br/> return (0); <br/>}< br/> int main () <br/>{< br/> thread_new (thread_main, null); <br/> sleep (5); <br/> (;;) <br/>{< br/> printf ("success"); <br/>}< br/> */<br/> return (0 ); <br/>}
Signal condition: here we set a signal processing function to print every 10 milliseconds. You can run it for a long time, and a deadlock will inevitably occur, that is, the screen will no longer print characters, at the same time, we can observe that every deadlock occurs when the main function is printed, because a deadlock occurs during signal switching.
Void gotsig (int n) <br/>{< br/> printf ("batch"); <br/>}< br/> void sig_safe (void) <br/>{< br/> struct itimerval value; <br/> struct sigaction sact; <br/> sigemptyset (& sact. sa_mask); <br/> sact. sa_flags = 0; <br/> sact. sa_handler = gotsig; <br/> sigaction (SIGALRM, & sact, NULL); <br/> value. it_interval. TV _sec = 0; <br/> value. it_interval. TV _usec = 10; <br/> value. it_value. TV _sec = 0; <br/> value. it_value. TV _usec = 1000; <br/> setitimer (ITIMER_REAL, & value, NULL); <br/> setbuf (stdout, NULL); <br/> while (1) {<br/> printf ("success"); <br/>}< br/>
References
Http://blog.chinaunix.net/u1/43233/showart_421573.html