Reference: https://www.cnblogs.com/ruizhang3/p/6418269.html
The location of the crash is as follows:
The gdb bt stack is as follows:
By analyzing the call stack and viewing the boost source code analysis, the source code call sequence is as follows:
It stands to reason that there should not be a crash at line 354 (!descriptor_data->shutdown_), but it actually crashes here, unless the resource that the if needs to access has been modified or destroyed.
Looking at the source code in epoll_reactor.ipp in boost, after analyzing the logic of the crash, it is found that the basic logic is as follows:
For each socket link, when the program calls the stop function to close or destroy the socket object
The epoll_reactor::deregister_descriptor function will be called in reactive_socket_service_base::destroy/close
Cancel the corresponding descriptor
When logging off, it will first determine whether descriptor_data is empty, if it is empty, return directly, if it is not empty, use mutex to lock.
After that, use the shutdown_ field in descriptor_data to determine whether it is closed.
If normal, the corresponding processing logic will be performed. After the processing is completed, descriptor_data will be set to empty.
Then the problem lies in the multi-threaded high concurrency situation (multiple calls to close operation), in the step of judging whether descriptor_data is empty and locking, descriptor_data may be empty by other threads
As a result, when the shutdown_ field in descriptor_data is used for judgment later, a segment fault is caused. Make the function not thread-safe.
Solution: Use mutex so that different threads will not close a socket connection at the same time.