2016-09-16 2 views
2

Poco :: Thread를 사용하여 문제가 있습니다. 이 코드는 약 4K 회 반복합니다. QNX5 용 GCC 4.6.1, POCO_VERSION 0x01040602로 구축되었습니다.Poco :: 여러 번 시작하여 끊어지면서 빠르게 연속으로 연결

#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(); 

    } 
} 

그러나 PThread를 직접 사용하면 문제가 없으며 Windows에서도 정상적으로 작동합니다. 도움이 되었으면 좋겠다.

+1

if (oThread.isRunning()) 부분을 제거해보십시오. 다음 두 가지 이유 때문에 필요하지 않습니다. 이미 완료된 스레드에 참여할 수 있으며 동시성으로 인해 if 블록의 본문이 실행되기 전에 술어가 잘못 될 수 있습니다. –

+0

@AlexeyGuseynov 사실 그것은 최소한의 예제를위한 해결책이며 술어에 대한 좋은 힌트입니다. 그러나, 전체 프로그램에서 isRunning() 스위치없이 충돌합니다. 나는 그것에 대해 재고 할 필요가있다. – Simon1X

+0

이제 전체 프로그램에서 실제 문제를 발견했습니다. 시작하기 전에 조인을합니다. 그것은 즉시 충돌로 이어집니다. 분명히, Poco는 처음 시작된 적이없는 스레드 (pthread와는 다른 동작)와의 결합을 허용하지 않습니다. – Simon1X

답변

2

Poco :: Thread의 내부 상태는 스레드로부터 안전하지 않습니다 (원자 적). 경쟁 조건은 start(), join()isRunning()이며 스레드 누수가 발생합니다 (현재는 Runnable에 가입하지 않음). -fsanitize와 ++ g을 사용

= -static-libtsan 스레드 (마시고 :: Thread`에서 내부적으로 사용) POCO의 마시고 :: 이벤트의 소스를 살펴보면

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. 

하는 것은 문제가있는 것 같다 구현의 일부.

대신 Poco::Thread을 사용하지 말고 std::thread (C++ 11)을 사용하는 것이 좋습니다.

+0

자세한 설명을 제공해 주셔서 감사합니다. 내부적으로 사용 된 이벤트 역시 제 추측이었습니다. 컴파일러에서 지원하는 경우 Std :: thread가 내 첫 번째 선택 항목이됩니다. – Simon1X