pthread线程和信号
所有的异步信号发到整个进程的所有线程(异步信号如kill, lwp_kill, sigsend, kill等调用产生的都是,异步信号也称为中断),而且所有线程共享信号的处理行为(即sigaction的设置,对于同一信号的设置,某一线程的更改会影响到所有线程)。但每个线程可以有自己的mask来阻止信号的发送,所以可以通过线程对mask的设置来决定信号发送到哪个线程。
设置mask的函数为:
1 2 |
#include <signal.h> int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset); |
此外,线程可以通过sleep(超过指定时间或调用的进程/线程捕捉到某个信号并从信号处理程序返回时,sleep返回)或者sigwait来等待一个或多个信号发生。
1 2 |
#include <signal.h> int pthread_sigwait(const sigset_t *restrict set, int *restrict signop); |
给进程发送信号可以调用kill,同样给线程调用信号可以使用pthread_kill
1 2 |
#include <signal.h> int pthread_kill(pthread_t thread, int signo); |
可以发送一个0的signo来检查线程是否存在,如果信号的默认行为是终止进程(例如SIGARLM),那么把该信号发送给某个线程会杀掉整个进程的所有线程。
另外注意ALARM是进程资源,并且所有线程共享相同的ALARM,设置一个alarm()会发送SIGARLM信号给所有线程,所以他们不可能互补干扰的使用alarm()。
here comes an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
/*threadsig.c*/ #include <signal.h> #include <pthread.h> #include <stdio.h> void sighandler(int signo); void * thr1_fn(void *arg) { pthread_t tid = pthread_self(); int rc; printf("thread 1 with tid:%un", tid); rc = sleep(60); if (rc != 0) printf("thread 1... interrupted at %d secondn", 60 - rc); printf("thread 1 endsn"); return NULL; } void * thr2_fn(void *arg) { struct sigaction action; pthread_t tid = pthread_self(); int rc, err; printf("thread 2 with tid:%un", tid); action.sa_flags = 0; action.sa_handler = sighandler; err = sigaction(SIGALRM, &action, NULL); rc = sleep(60); if (rc != 0) printf("thread 2... interrupted at %d secondn", 60 - rc); printf("thread 2 endsn"); return NULL; } void * thr3_fn(void *arg) { pthread_t tid = pthread_self(); sigset_t mask; int rc, err; printf("thread 3 with tid%un", tid); sigemptyset(&mask); /* 初始化mask信号集 */ sigaddset(&mask, SIGALRM); err = pthread_sigmask(SIG_BLOCK, &mask, NULL); if (err != 0) { printf("%d, %s/n", rc, strerror(rc)); return NULL; } rc = sleep(60); if (rc != 0) printf("thread 3... interrupted at %d secondn", 60 - rc); printf("thread 3 endsn"); return NULL; return NULL; } int main(void) { int rc, err; pthread_t thr1, thr2, thr3, thrm = pthread_self(); printf("thread main with pid %un", (unsigned int)thrm); err = pthread_create(&thr1, NULL, thr1_fn, NULL); if (err != 0) { printf("error in creating pthread:%dt%sn",err, strerror(rc)); exit(1); } /* pthread_kill(thr1, SIGALRM); send a SIGARLM signal to thr1 before thr2 set the signal handler, then the whole process will be terminated*/ err = pthread_create(&thr2, NULL, thr2_fn, NULL); if (err != 0) { printf("error in creating pthread:%dt%sn",err, strerror(rc)); exit(1); } err = pthread_create(&thr3, NULL, thr3_fn, NULL); if (err != 0) { printf("error in creating pthread:%dt%sn",err, strerror(rc)); exit(1); } sleep(3); pthread_kill(thr1, SIGALRM); pthread_kill(thr2, SIGALRM); pthread_kill(thr3, SIGALRM); pthread_join(thr1, NULL); /*wait for the threads to complete.*/ pthread_join(thr2, NULL); pthread_join(thr3, NULL); printf("main endsn"); return 0; } void sighandler(int signo) { pthread_t tid = pthread_self(); printf("thread with pid:%u receive signo:%dn", tid, signo); return; } |
luffy@luffy-laptop:~/workspace/myapue$ ./threadsig
thread main with pid 3557979936
thread 1 with tid:3549923072
thread 2 with tid:3541530368
thread 3 with tid3533137664
thread with pid:3549923072 receive signo:14
thread with pid:3541530368 receive signo:14
thread 2… interrupted at 3 second
thread 1… interrupted at 3 second
thread 1 ends
thread 2 ends #then wait for 27 seconds and thread-3 ends
thread 3 ends
main ends
thr2设置的信号处理程序sighandler也应用到其他线程,thr3由于设置mask所有阻塞了SIGARLM信号。
Reference:
APUE
线程信号 http://blog.csdn.net/copal/article/details/5454279