本文主要是介绍thread termination,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
轉載自http://stackoverflow.com/questions/6621785/posix-pthread-programming
There are mainly two approaches for thread termination.
- Use a cancellation point. The thread will terminate when requested to cancel and it reaches a cancellation point, thus ending execution in a controlled fashion;
- Use a signal. Have the threads install a signal handler which provides a mechanism for termination (setting a flag and reacting to
EINTR
).
Both approaches has caveats. Refer to kill thread in pthread for more details.
In your case, it seems a good opportunity to use cancellation points. I will work with a commented example. The error-checking has been omitted for clarity.
1 #define _POSIX_C_SOURCE 200809L 2 #include <pthread.h> 3 #include <signal.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 8 void sigint(int signo) { 9 (void)signo; 10 } 11 12 void *thread(void *argument) { 13 (void)argument; 14 for (;;) { 15 // Do something useful. 16 printf("Thread %u running.\n", *(unsigned int*)argument); 17 18 // sleep() is a cancellation point in this example. 19 sleep(1); 20 } 21 return NULL; 22 } 23 24 int main(void) { 25 // Block the SIGINT signal. The threads will inherit the signal mask. 26 // This will avoid them catching SIGINT instead of this thread. 27 sigset_t sigset, oldset; 28 sigemptyset(&sigset); 29 sigaddset(&sigset, SIGINT); 30 pthread_sigmask(SIG_BLOCK, &sigset, &oldset); 31 32 // Spawn the two threads. 33 pthread_t thread1, thread2; 34 pthread_create(&thread1, NULL, thread, &(unsigned int){1}); 35 pthread_create(&thread2, NULL, thread, &(unsigned int){2}); 36 37 // Install the signal handler for SIGINT. 38 struct sigaction s; 39 s.sa_handler = sigint; 40 sigemptyset(&s.sa_mask); 41 s.sa_flags = 0; 42 sigaction(SIGINT, &s, NULL); 43 44 // Restore the old signal mask only for this thread. 45 pthread_sigmask(SIG_SETMASK, &oldset, NULL); 46 47 // Wait for SIGINT to arrive. 48 pause(); 49 50 // Cancel both threads. 51 pthread_cancel(thread1); 52 pthread_cancel(thread2); 53 54 // Join both threads. 55 pthread_join(thread1, NULL); 56 pthread_join(thread2, NULL); 57 58 // Done. 59 puts("Terminated."); 60 return EXIT_SUCCESS; 61 }
The need for blocking/unblocking signals is that if you send SIGINT to the process, any thread may be able to catch it. You do so before spawning the threads to avoid having them doing it by themselves and needing to synchronize with the parent. After the threads are created, you restore the mask and install a handler.
Cancellation points can be tricky if the threads allocates a lot of resources; in that case, you will have to use pthread_cleanup_push()
and pthread_cleanup_pop()
, which are a mess. But the approach is feasible and rather elegant if used properly.
这篇关于thread termination的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!