Signal 13 was raised(SIGPIPE管道破裂)

本文详细介绍了在苹果系统中使用socket编程时遇到SIGPIPE信号的常见问题及其解决方法,包括如何忽略SIGPIPE信号、重新定义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

在 Flask 应用中遇到 `ImportError when importing 'qpp'` 错误,通常表示 Python 解释器无法找到名为 `qpp` 的模块或对象。此类错误可能由多种原因引起,包括模块路径配置不正确、拼写错误、循环引用或依赖版本不兼容等。 首先应确认模块是否存在以及其命名是否准确。Flask 项目中的导入错误常源于模块未被正确识别,例如文件名与模块名不一致、缺少 `__init__.py` 文件,或者相对导入路径设置不当。如果 `qpp` 是一个本地模块,应确保其位于 Python 能够搜索到的路径中,可通过以下命令查看当前解释器的模块搜索路径: ```python import sys print(sys.path) ``` 若路径未包含所需目录,可在入口文件中手动添加路径: ```python import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), 'your_module_directory')) ``` 此外,某些情况下,Flask 项目的结构问题也可能导致导入失败。例如,在使用 Flask-Script 或 Flask-Migrate 时,若存在循环引用(如 A 模块导入 B 模块,而 B 又导入 A),将导致类似错误。检查并重构代码以避免循环依赖是解决此类问题的关键[^3]。 如果 `qpp` 是第三方库,则需确保该库已正确安装。可以通过以下命令安装并验证其是否存在: ```bash pip install qpp pip show qpp ``` 若提示“ModuleNotFoundError”或“ImportError”,则可能是包名拼写错误或该库并未发布至 PyPI。此时应确认实际库名,并尝试更正导入语句。 对于虚拟环境的使用,确保当前运行 Flask 的解释器与目标环境一致。可以使用以下命令激活虚拟环境后再运行应用: ```bash source venv/bin/activate # Linux/macOS venv\Scripts\activate # Windows flask run ``` 若上述方法均未能解决问题,建议检查 Flask 应用的入口文件(如 `app.py` 或 `wsgi.py`)中是否存在语法错误、拼写错误或不兼容的导入方式。例如,Flask 在较新版本中对 Jinja2 的依赖有所调整,若使用旧版 Flask(如 1.1.2),可能会因 Jinja2 中的 API 更改而导致导入失败[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值