Crash与信号

什么是信号

信号(signal)是一种XPC通信方式。
signal是一个4字节的无符号整形数字,在iOS/OSX中定义了31个已知的信号;
在Unix系统中,crash仅仅是singal触发的一个行为。signal的用途/产生包括但不限于:

  • 显示调用kill,killpg触发signal
  • 改变子进程的状态
  • 致命性中断
  • job控制
  • timer过期
  • 各种通知,如cpu resource limit或file size limit等

signal会导致以下几种行为(action):

  • Terminate 杀死进程
  • Dump core 杀死进程并创建一个core file
  • Stop 暂停进程suspend
  • Continue 恢复进程resume
  • Ignore 忽略/丢弃该信号

每个signal号都有默认的action,可以通过sigaction() 系统调用来修改signal actions,为SIG_DFL(use the default action),或者修改为SIG_IGN(ignore the signal),或者指定signal handler function(捕获signal)

一般的异常捕获工具会基于上述方式来修改signal的actions或执行signal handler,从而达到异常捕获的目的。我们也可以通过修改signal actions来达到让应用直接忽略某个信号,而不发生异常退出。但是这也有个别例外情况,比如SIGKILL,SIGSTOP 无法被捕获或忽略。

信号如何产生

使用过kill函数来达到向某个进程pid发送signal:

int kill(pid_t pid, int sig);

pid>0,则sig会发送给对应process id的进程;

pid=0,则会发给所有和sender具有相同group id的进程;

pid=-1,如果具有超级权限,则sig会发给除了系统进程以及sender进程外的所有进程;否则sig会发给除了sender以外的所有当前user下的进程;

pid<-1,效果等同killpg

使用pthread_kill向某个线程发送signal:

int pthread_kill(pthread_t thread, int sig);
信号与多线程

signal的分发实现是基于per-thread signal masks的,它确保了多线程情况下信号依旧能被顺序处理,即线程a在处理信号时,其它线程的信号会被阻塞。系统提供了pthread_sigmask()调用来修改signal mask;默认情况下子线程的masks是和创建它的线程是一致的。

如果一个信号是由于trap,illegal instruction或arithmetic exception则该信号会被分发给对应触发的线程(主要是synchronous signal);否则这些信号会被发给第一个不阻塞该signal的线程;

注意:SIGKILL,SIGSTOP,SIGTERM会影响整个进程;

当发送信号时,接收者signal_handler会收到siginfo_t,这个结构存储了详细的信号信息;siginfo_t结构如下

typedef struct __siginfo {
	int	si_signo;		/* signal number */
	int	si_errno;		/* errno association */
	int	si_code;		/* signal code */
	pid_t	si_pid;			/* sending process */
	uid_t	si_uid;			/* sender's ruid */
	int	si_status;		/*
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值