Message from debugger: Terminated due to signal 13
最近Xcode编译时,总是发生这样一个错误,程序异常退出,并且不会留下其它信息判断是什么问题。因为之前出错,也是类似这样一个错误,百度并没有得到什么有用的信息,所以这次直接硬刚,因为每次程序都是结束在发送数据发送失败那里。。。。。。
后面才发现,之前那个类似的错误,是signal 9
http://www.voidcn.com/article/p-agnkvxam-xu.html
最后百度,在上面这个链接找到了原因:
错误产生的原因:尝试send到一个已关闭的socket上两次
这个错误,不能通过try catch捕捉和避免
管道另一端没有进程接收数据,导致管道破裂而崩溃。
socket或管道,当自己主动关闭,资源被苹果系统回收,对方关闭时,当再次通过socket或pipe的文件描述符发送消息会出现系统级别的崩溃
(管道破裂,signal 13。它的级别和内存使用或释放异常一直,由于是系统级别崩溃,所以不能通过@try{}@catch (NSException *exception) {}捕获到异常,而是直接app崩溃)。
如果尝试send到一个已关闭的 socket上两次,就会出现此信号
也就是用协议TCP的socket编程,服务器是不能知道客户机什么时候已经关闭了socket,导致还在向该已关闭的socket上send,导致SIGPIPE。
而系统默认产生SIGPIPE信号的措施是关闭进程,所以出现了服务器也退出。
在苹果手机上尝试过重新定义遇到SIGPIPE的措施,signal(SIGPIPE, SIG_IGN);结果仍旧崩溃
所以若是苹果系统回收io资源的情况下,没有办法通过这种方案解决。只需要发现这种情况忽略这种异常(int set = 1;
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
使用使用 signal(SIGPIPE, SIG_IGN) 忽略SIGPIPE或是 自己设置handle处理函数。
经实验在ios7模拟器上虽然xcode还是会捕获SIGPIPE,但是程序不会崩溃,继续后可以执行。但是在真机上依然会崩溃。)
在前台时,重建线程,重新申请管道就可以。注意:苹果在后台断网8分钟以后,无法申请io资源。
signal 13 对应就是 SIGPIPE ,网上对与这个Signal 的解释是这样的:管道破裂。
这个信号通常在进程间通信产生,比如采用FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到SIGPIPE信号。
此外用Socket通信的两个进程,写进程在写Socket的时候,读进程已经终止。
网上了解到的情况是使用socket的时候一般都会收到这个SIGPIPE 信号,处理方法大部分都是忽略。
我们需要在send的时候检测到服务器已经关闭连接,进行重新连接。
正常情况下send函数返回-1表示发送失败,但是在IOS上SIGPIPE在send返回之前就终止了进程
所以我们需要忽略SIGPIPE,让send正常返回-1,然后重新连接服务器。
这个是实际的例子及XCode用debug模式打印的控制台异常日志:
当守护线程由于应用切换到后台8分钟及以上,无网络时,苹果系统挂起了守护线程和长连接。
当然也有低概率出现,当应用切换到后台立刻切换到前台,正在进行io操作的线程被杀死,已经通过打印日志打印出了这种小概率事件。
当切换到前台,检查出长连接线程异常,重启了长连接线程,新的长连接线程通过本地管道向守护线程发送监控消息
由于守护线程已经挂起(被系统回收资源,本地管道被系统关闭),导致发生管道破裂类型的崩溃,app的运行。