chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.88k stars 1.21k forks source link

Thread performing synchronous read on serial port does not join after port is closed (Linux Only) #814

Open jjELT opened 3 years ago

jjELT commented 3 years ago

Observation

On Linux, a thread, hanging in boost::asio::serial_port::read_some does not std::thread::join after boost::asio::serial_port::close is called from another thread.

This applies to Boost v1.72.0 and v1.76.0 (other versions not tested).

The problem does not occur in Windows.

Sample Code

Starting a thread to synchronously read data from the serial port:

std::shared_ptr<std::thread> receivingThread = std::make_shared<std::thread>([this]() {
    LOG_TRACE(logger) << "Receiving thread started";
    try
    {
        size_t amountOfReceivedBytes = serialPort->read_some(boost::asio::buffer(receiveBuffer));
    }
    catch (std::exception &e)
    {
        LOG_WARN(logger) << "read_some interrupted " << e.what();
    }
    LOG_TRACE(logger) << "Receiving thread stopped";
});

Closing the serial port in the main thread:

// Close serial port.
if (serialPort && serialPort->is_open())
{
    serialPort->close();
    LOG_DEBUG(logger) << "Successfully closed the serial port.";
}
...
if (receivingThread)
{
    LOG_TRACE(logger) << "Waiting for receiving thread to finish.";
    receivingThread->join();
    LOG_TRACE(logger) << "Receiving thread finished.";
}
LOG_DEBUG(logger) << "Threads successfully stopped.";

The line LOG_TRACE(logger) << "Receiving thread finished."; is never reached.

Workaround

Detaching the thread

...
if (receivingThread)
{
    LOG_TRACE(logger) << "Detaching thread without waiting for it to finish.";
    receivingThread->detach();
    LOG_TRACE(logger) << "Thread detached.";
}
LOG_DEBUG(logger) << "Threads successfully stopped.";

serves as a workaround.

On Linux the lines

LOG_WARN(logger) << "read_some interrupted " << e.what();
LOG_TRACE(logger) << "Receiving thread stopped";

are never reached though, contrary to Windows, where they are reached! So I guess the thread is just forcefully killed by the OS eventually?!

See logs: elt-cpp-core-test-app_LINUX.log elt-cpp-core-test-app_WINDOWS.log

Possibly Related

Could be related to #762 and #779.

jjELT commented 3 years ago

Ran the test on two Linuxes, with different kernels, but the same result, so the problem seems to be unrelated to the kernel.

The tested distributions and kernels are:

Linux Mint 20.1: 5.4.0-70-generic #78-Ubuntu SMP Fri Mar 19 13:29:52 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux CentOS 8.2: 4.18.0-193.19.1.el8_2.x86_64 #1 SMP Mon Sep 14 14:37:00 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux