记嵌入式linux平台下Boost.Asio中TCP套接字关闭的崩溃问题
参考:https://www.cnblogs.com/ruizhang3/p/6418269.html
崩溃位置如下图:
gdb bt堆栈如下图:
通过分析调用堆栈,查看boost源码分析,源码调用顺序如下:
按理说,在354行if (!descriptor_data->shutdown_)处不应该崩溃,但是实际就崩溃在这里,除非if需要访问的资源已经被修改或者破坏。
查看boost中epoll_reactor.ipp中的源码,对奔溃处的逻辑进行分析后发现其基本逻辑如下:
对于每个socket链接,在程序调用停止函数对socket对象进行关闭或者销毁时
会在reactive_socket_service_base::destroy/close调用epoll_reactor::deregister_descriptor函数
注销相应的descriptor
在注销时,首先会判断descriptor_data是否为空,若为空则直接返回,若不为空则使用mutex进行加锁。
之后,使用descriptor_data中的shutdown_字段判断是否是已关闭状态。
若正常便进行相应处理逻辑。在处理完成之后会将descriptor_data置为空。
那么问题就在于在多线程高并发的情况(多次调用close操作),判断descriptor_data是否为空和加锁这一步骤中,descriptor_data可能会被其他线程置为空
导致之后使用descriptor_data中的shutdown_字段判断时,造成segment fault。使得该函数不是线程安全的函数。
解决方案:使用mutex使得不同线程不会同时对一个socket连接进行关闭操作。