#include<signal.h> intsigprocmask(int how, constsigset_t *set, sigset_t *oldset); how 值: SIG_BLOCK:把set里信号添加到blocked列表 SIG_UNBLOCK:从blocked里删除set里的信号 SIG_SETMASK:block=set 把旧的blocked保存到oldset set 为NULL,读取现在的屏蔽值
int sigemptyset(sigset_t *set); 初始化set为0 intsigfillset(sigset_t *set); 所有信号填入set intsigaddset(sigset_t *set, int signum); 填入signum intsigdelset(sigset_t *set, int signum); 删除signum 返回:如果成功则为 o, 若出错则为-1 。 intsigismember(constsigset_t *set, int signum); 返回:若 signum 是 set 的成员则为 1, 如果不是则为 0 若出错则为-1
grxer@Ubuntu22-wsl ~/s/test> gcc -g -O2 -o test test.c grxer@Ubuntu22-wsl ~/s/test> ./test ^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^Z fish: Job 6, './test' has stopped
非本地跳转
整数除0会SIGFPE
grxer@Ubuntu22-wsl ~/s/test> ./test fish: Job 1, './test' terminated by signal SIGFPE (Floating point exception)
本来想着改掉SIGFPE的默认处理,看看整数除0后结果是什么样
#include<stdio.h> #include<signal.h> #include<assert.h> #include<stdlib.h> voidsignal_handler(int sig) { puts("xxx"); } intmain() { __sighandler_t rs = signal(SIGFPE, signal_handler); assert(rs != SIG_ERR); int z = 12; int t = 0; z = z / t; printf("%d\n", z); }
结果忘了信号处理函数过后会返回到断点处,也就是导致这个异常的语句处z = z / t;然后就会一直导致SIGFPE,goto只能实现函数内的跳转,其实goto在汇编层就是一个无条件的跳转jmp,他也没能力实现函数间的跳转,除非他能把栈给平了,寄存器修正了
使用setjmp就可以做到
#include<setjmp.h> intsetjmp(jmp_buf env); intsigsetjmp(sigjmp_buf env, int savesigs); voidlongjmp(jmp_buf env, int val); voidsiglongjmp(sigjmp_buf env, int val);
setjmp把当前程序各种信息保存到env里(typically, the stack pointer, the instruction pointer, possibly the values of other registers and the signal mask),直接调用返回0,
sigsetjmp() and siglongjmp() sigsetjmp() and siglongjmp() also perform nonlocal gotos, but provide predictable handling of the process signal mask.
If, and only if, the savesigs argument provided to sigsetjmp() is non‐ zero, the process's current signal mask is saved in env and will be re‐ stored if a siglongjmp() is later performed with this env.
sigpending()用于获取当前进程已经被阻塞但尚未处理的信号集合
#include<stdio.h> #include<signal.h> #include<assert.h> #include<setjmp.h> #include<stdlib.h> jmp_buf env; intmain() { sigset_t mask, pendmask, blockmask; sigemptyset(&mask); sigemptyset(&pendmask); sigemptyset(&blockmask); sigaddset(&mask, SIGINT); sigprocmask(SIG_BLOCK, &mask, NULL); // if (sigsetjmp(env, 666) != 0) { if (setjmp(env) != 0) { sigpending(&pendmask); sigprocmask(SIG_BLOCK, NULL, &blockmask); if (sigismember(&blockmask, SIGINT)) puts("in blockmask"); else puts("not in blockmask"); if (sigismember(&pendmask, SIGINT)) puts("in pendmask"); else puts("not in pendmask"); exit(0); } sleep(2);//时间间隔我疯狂按ctrl c :) // siglongjmp(env, 1); longjmp(env, 1); }
使用sigsetjmp时
grxer@Ubuntu22-wsl ~/s/test> ./test ^C^C^C^Cin blockmask in pendmask
使用setjmp
grxer@Ubuntu22-wsl ~/s/test> ./test ^C^C^C^Cin blockmask in pendmask