Signal 13 was raised(SIGPIPE管道破裂)

管道另一端没有进程接收数据,导致管道破裂而崩溃。
socket或管道,当自己主动关闭,资源被苹果系统回收,对方关闭时,当再次通过socket或pipe的文件描述符发送消息会出现系统级别的崩溃(管道破裂,signal 13。它的级别和内存使用或释放异常一直,由于是系统级别崩溃,所以不能通过@try{}@catch (NSException *exception) {
}捕获到异常,而是直接app崩溃)。
如果尝试send到一个已关闭的 socket上两次,就会出现此信号,也就是用协议TCP的socket编程,服务器是不能知道客户机什么时候已经关闭了socket,导致还在向该已关 闭的socket上send,导致SIGPIPE。
而系统默认产生SIGPIPE信号的措施是关闭进程,所以出现了服务器也退出。
在苹果手机上尝试过重新定义遇到SIGPIPE的措施,signal(SIGPIPE, SIG_IGN);虽然xcode还是会捕获SIGPIPE,但是程序不会崩溃,继续后可以执行。所以若是苹果系统回收io资源的情况下,没有办法通过这种方案解决。只需要发现这种情况忽略这种异常(setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, SIG_IGN, sizeof(int));,使用使用 signal(SIGPIPE, SIG_IGN) 忽略SIGPIPE或是 自己设置handle处理函数。经实验在ios7模拟器上虽然xcode还是会捕获SIGPIPE,但是程序不会崩溃,继续后可以执行。有人说在真机上依然会崩溃。我测试没有发现崩溃,只是通过xcode捕获到SIGPIPE,但是没有崩溃)在前台时,重建线程,重新申请管道就可以。注意:苹果在后台断网8分钟以后,无法申请io资源,再使用管道或socket前用(setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, SIG_IGN, sizeof(int));来忽略管道破裂消息,最好关闭后置为-1,使用时判断下是否为-1,防止使用已经关闭的管道或socket。当然玩管道或socket没有一个喜欢自己的应用因为管道破裂而崩溃(程序健壮性问题),还是在初始化时用signal(SIGPIPE, SIG_IGN);来一下整体的全体忽略,然后再用(setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, SIG_IGN, sizeof(int));来下具体对象具体对待。
signal 13 对应就是 SIGPIPE ,网上对与这个Signal 的解释是这样的:
管道破裂。这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。

网上了解到的情况是使用socket的时候一般都会收到这个SIGPIPE 信号,处理方法大部分都是忽略,毕竟没有一个人希望自己的应用不明不白的挂掉。

不光在send,write时会引起管道破裂,关闭socket,管道时也会出现管道破裂。所以关闭文件描述符时,要判断文件描述符的有效性,忽略SIGPIPE,关闭完毕要把它置为无效的-1。

我们需要在send的时候检测到服务器已经关闭连接,进行重新连接。正常情况下send函数返回-1表示发送失败,但是在IOS上SIGPIPE在send返回之前就终止了进程,所以我们需要忽略SIGPIPE,让send正常返回-1,然后重新连接服务器。
这个是实际的例子及XCode用debug模式打印的控制台异常日志:
当守护线程由于应用切换到后台8分钟及以上,无网络时,苹果系统挂起了守护线程和长连接。当然也有低概率出现,当应用切换到后台立刻切换到前台,正在进行io操作的线程被杀死,已经通过打印日志打印出了这种小概率事件。当切换到前台,检查出长连接线程异常,重启了长连接线程,新的长连接线程通过本地管道向守护线程发送监控消息,由于守护线程已经挂起(被系统回收资源,本地管道被系统关闭),导致发生管道破裂类型的崩溃,app的运行。
控制台打印的崩溃日志:
Message from debugger: Terminated due to memory issue

你可能感兴趣的:(Signal 13 was raised(SIGPIPE管道破裂))