Simon1X Simon1X - 2 months ago 7
C++ Question

Poco::Thread hangup on multiple start and join in quick succession

I'm stuck with an issue using Poco::Thread. This Code hangs at around 4K iterations. Built with GCC 4.6.1 for QNX5, POCO_VERSION 0x01040602.

#include "Poco/Thread.h"
using namespace Poco;

class SignalAdapter: public Runnable
{
public:
SignalAdapter()
{}

virtual void run()
{
//printf( "This is thread %d\n", Thread::currentTid() );
}
};

int main() {
Thread oThread;
SignalAdapter oSignalAdapter{};

for (auto i = 0; i < 1e5; ++i)
{
oThread.start(oSignalAdapter);
if (oThread.isRunning())
oThread.join();

}
}


However, it works fine using PThread directly, it also works fine on Windows. I would be glad for some help.

Answer

The internal state of a Poco::Thread is not thread safe (atomic). You will get a race condition in start(), join() and isRunning() leading to thread leaks (not joining the current Runnable).

Using g++ with -fsanitize=thread -static-libtsan:

WARNING: ThreadSanitizer: thread leak (pid=24366)
  Thread T1 (tid=32349, finished) created by main thread at:
    #0 pthread_create <null> (Test+0x0000004945e7)
    #1 Poco::ThreadImpl::startImpl(Poco::Runnable&) <null> (libPocoFoundation.so.20+0x0000000f8d67)
    #2 __libc_start_main <null> (libc.so.6+0x00000002082f)

  And 11 more similar thread leaks.

Looking into the sources of POCO, the Poco::Event (used internally by Poco::Thread`) seems to be the problematic part of the implementation.

I suggest not to use Poco::Thread and use std::thread (C++11), instead.