关于Flutter使用socket在iOS下报 Terminated due to signal 13的采坑记录
说明
在flutter开发中,使用到了socket,但是在调试过程中,iOS 13系统上发现了比较费解的BUG。
- 当前应用切换到后台,打开其他应用,等到5到10分钟后,再把当前应用切换到前台
- 切换到后台然后再切换回前台
- 息屏之后再解锁手机
进行如上操作的时候会出现APP直接退出的情况(闪退现象),但与平常闪退情况不同的是,链接编译器调试的时候,编译器不会捕捉到相关的crash信息,编译器与手机的链接会直接中断。
开始尝试解决问题
1. 在APPdelegate里集成Bugly
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//signal(SIGPIPE, SIG_IGN);//忽略信号
[GeneratedPluginRegistrant registerWithRegistry:self];
[Bugly startWithAppId:@"Bugly配置的APPID"];
FlutterViewController *controller = (FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel *versionChannel = [FlutterMethodChannel methodChannelWithName:@"version" binaryMessenger:controller];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
经过测试,Bugly日志里并没有日志,所以Bugly的方式不可行。
2. 真机测试
在下列方法中打断点进行测试
// app启动或者app从后台进入前台都会调用这`在这里插入代码片`个方法
- (void)applicationDidBecomeActive:(UIApplication *)application{
}
// app从后台进入前台都会调用这个方法
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
//进入后台
- (void)applicationDidEnterBackground:(UIApplication *)application{
}
经过测试发现APP由后台进入前台时,控制台报 Message from debugger: Terminated due to signal 13
错误信息
追踪Terminated due to signal 13
经过一系列查阅发现,在 signal.h 文件中, 可以发现其定义如下:
#define SIGPLPE 13 /* write on a pipe with no one to read it */
- 管道破裂,这个信号通常在进程间通信产生,比如采用 FIFO(管道)通信的两个进程,读管道没打开或者意外终止就往管道写,写进程会收到 SIGPIPE 信号. 此外用 Socket 通信的两个进程,写进程在写 Socket 的时候,读进程已经终止. 另外, 在send/write 时会引起管道破裂,关闭 Socket, 管道时也会出现管道破裂. 使用 Socket 一般都会收到这个SIGPIPE 信号.简单来说就是和socket通信以及数据的读写相关联。这样一来就能大体猜到为什么在切换到前台或者重新解锁手机的时候出现crash现象了。
- signal 13 这种错误是系统发出来的, 和内存使用异常和野指针一样,由于是系统级别崩溃,所以不能通过@try,catch捕获异常。
- 我们在苹果的开发者文档 (https://developer.apple.com)中发现了相关的解决方案。
解决方案
- 忽略这类信号
在你调用你的SDK之前,调用如下代码signal(SIGPIPE, SIG_IGN)
;
// app启动或者app从后台进入前台都会调用这个方法
1. (void)applicationDidBecomeActive:(UIApplication *)application{
signal(SIGPIPE, SIG_IGN);//Ignore signal
}
// app从后台进入前台都会调用这个方法
2. (void)applicationWillEnterForeground:(UIApplication *)application {
signal(SIGPIPE, SIG_IGN);//Ignore signal
}
- 修改socket通信的源码 此处省略多行代码,当然有经历的小伙伴,最好尝试一下,毕竟这是最佳解决问题的方式
运行
重新编译项目,运行,测试,最后发现问题已解决。
参考文档
作者:豆大人007
链接:https://www.jianshu.com/p/7bef6f1c572d
来源:简书