undefined reference to `pthread_create' Error when making C++11 application with ASIO and std::thread

35,498

Solution 1

The fact that a program is written in C++11 has no bearing on with whether or not it needs to be linked with the pthread library. It needs to link that library if it requires Posix threads.

C++11 provides the std::thread class and each conforming compiler's standard library must implement the functionality of that class using some native threads API hosted by the target system. GCC implements it using pthreads, so you cannot any build a program that creates std::thread objects with GCC unless you link it with -pthread. This fact is unconnected with asio.

LATER

I actually built a program without pthread using std::std just using -std=c++11

I think you are mistaken and confused by the fact that some Windows ports of GCC link libpthread by default. E.g. if your example program is in thread.cpp I can successfully build it in Windows with TDM-GCC 4.9.2 so:

>g++ -std=c++11 -o test_thread thread.cpp

But if you build it in verbose mode:

>g++ -v -std=c++11 -o test_thread thread.cpp

you can see that a great many library options are passed to the linker behind the scenes, in particular -lpthread:

>g++ -v -std=c++11 -o test_thread thread.cpp 2>&1 | grep -Po 'pass-through=-lpthread' -
pass-through=-lpthread

And on Linux you will not link libpthread unless you ask:

$ g++ -std=c++11 -o test_thread thread.cpp
/tmp/ccpyEles.o: In function `std::thread::thread<void (&)()>(void (&)())':
thread.cpp:(.text._ZNSt6threadC2IRFvvEJEEEOT_DpOT0_[_ZNSt6threadC5IRFvvEJEEEOT_DpOT0_]+0x7d): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

Solution 2

During excution of code use g++ ssss(your code name).cpp -std=c++11 -pthread

it will work

Solution 3

1. std::thread doesn't need -pthread

Here is what I dug out from ASIO, and let me show the simple example first. In CentOS 6.5 32 bit, and in Eclipse, using g++4.9.3, the following code builds with -std=c++11 only, no need to say -lpthread

std::string make_greeting_string()
{
    auto now = std::chrono::system_clock::now();
    const auto in_time_t = std::chrono::system_clock::to_time_t(now);

    std::stringstream ss;
    //ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
    ss << "Greetings"<<45;
    return ss.str();
}
int main() {
    std::thread thread1(make_greeting_string);
    //test2();
    thread1.join();
    cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
    return 0;
}

Once I add tes2() in main, it fails with undefined reference to `pthread_create'

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   std::cout<<"Hello World! It's me, thread #%ld!"<<tid<<std::endl;
   pthread_exit(NULL);
}


void test2()
{
    pthread_t threads[NUM_THREADS];
    int rc;
    long t;
    for(t=0;t<NUM_THREADS;t++){
        std::cout<<"In main: creating thread %ld"<<t<<std::endl;
        rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
        if (rc){
            std::cout<<"ERROR; return code from pthread_create() is "<<rc<<std::endl;
            exit(-1);
        }
    }
}

2. Source of ASIO's dependency on -pthread

First, there are code in standalone ASIO which uses posix thread but can also use std. The order should be rearranged to use std first when both are defined. Code example from static_mutex.hpp line 27

#elif defined(ASIO_HAS_PTHREADS)  
#include "asio/detail/posix_static_mutex.hpp"
#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)
#include "asio/detail/std_static_mutex.hpp"

Second, there are still two files that need posix: signal_blocker.hpp and tss_ptr.hpp. The make will fail because only Windows and POSIX are supported

I don't know whether it's possible to completely rewrite the two files to use c++11, but these two files are the source of the dependency on -lpthread, not std::thread.

update

tss_ptr.hpp states that if ASIO_HAS_THREAD_KEYWORD_EXTENSION is defined, it doesn't need pthread. After I defined this in symbols, the make errors dropped by half, indicating, only the signal_blocker.hpp is the source of this dependency.

affects signal_set_service.ipp

case asio::io_service::fork_child:
    if (state->fork_prepared_)
    {
      asio::detail::signal_blocker blocker;
      close_descriptors();
      open_descriptors();
      int read_descriptor = state->read_descriptor_;
      state->fork_prepared_ = false;
      lock.unlock();
      reactor_.register_internal_descriptor(reactor::read_op,
          read_descriptor, reactor_data_, new pipe_read_op);
    }
    break;

and select_reactor.ipp

{
#if defined(ASIO_HAS_IOCP)
  asio::detail::signal_blocker sb;
  thread_ = new asio::detail::thread(
      bind_handler(&select_reactor::call_run_thread, this));
#endif // defined(ASIO_HAS_IOCP)
}
Share:
35,498
Splash
Author by

Splash

1 year old Java programmer

Updated on January 29, 2020

Comments

  • Splash
    Splash over 4 years

    I set Eclipse (Actually Xilinx SDK but based on Eclipse), and g++4.9.2, to compile a project which uses standalone ASIO and I used -std=c++11 in the Properties -> C/C++ Build -> Settings -> Tool Settings -> Other flags so it can compile using all C++11 features.

    I also set ASIO_HAS_STD_THREAD, ASIO_STANDALONE and so on in C/C++ General Symbols, and I expect that the ASIO header will use std::thread instead of pthread. However, I still see Error from make:

    undefined reference to pthread_create, 
    ..asio-1.10.6\include\asio\detail\impl\posix_thread.ipp
    and posix_tss_ptr.hpp
    

    so the problem is, since I am using C++11, and specified ASIO_HAS_STD_THREAD but not ASIO_HAS_PTHREADS, the posix_thread.ipp should not be even included (through posix_thread.hpp), according to thread.hpp in ASIO:

    #if !defined(ASIO_HAS_THREADS)
    # include "asio/detail/null_thread.hpp"
    #elif defined(ASIO_WINDOWS)
    # if defined(UNDER_CE)
    #  include "asio/detail/wince_thread.hpp"
    # else
    #  include "asio/detail/win_thread.hpp"
    # endif
    #elif defined(ASIO_HAS_PTHREADS)
    # include "asio/detail/posix_thread.hpp"
    #elif defined(ASIO_HAS_STD_THREAD)
    # include "asio/detail/std_thread.hpp"
    #else
    # error Only Windows, POSIX and std::thread are supported!
    #endif
    

    Suspect 1 -pthread

    Contrary to most people believe, C++11 doesn't need the -pthread and I have tried to compile a simple project without -pthread in Eclipse. However, you can correct me if I am wrong. When I put -pthread in the linker option, it does compile, however I felt I don't want the pthread if not necessary.

    Suspect 2 - ASIO makefile

    When I search the posix_tss_ptr.hpp, I found also in Makefile.am. I wonder whether this affect the error?

    So what is the cause of the problem? If not the above two suspect? I hope the solution can be still using pure C++11 way, not to use pthread if my reasoning is correct.

    Update

    I found that ASIO_HAS_PTHREADS is defined not by me and that's why ASIO uses POSIX threads somewhere and the linker then needs the option -pthread. Then I traced down to the asio/detail/signal_blocker.hpp by using #error directive. There are only two places that it is defined and they are in ASIO config.hpp

    #  if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
    #   define ASIO_HAS_PTHREADS 1
    #  elif defined(_POSIX_THREADS)
    #   define ASIO_HAS_PTHREADS 1
    

    ASIO still replies on POSIX THREADS or Windows for signal_blocker.hpp shown below. That's why ASIO still needs pthread.

    #if !defined(ASIO_HAS_THREADS) || defined(ASIO_WINDOWS) \
      || defined(ASIO_WINDOWS_RUNTIME) \
      || defined(__CYGWIN__) || defined(__SYMBIAN32__)
    typedef null_signal_blocker signal_blocker;
    #elif defined(ASIO_HAS_PTHREADS)
    typedef posix_signal_blocker signal_blocker;
    #endif
    

    And _PTHREADS is defined from the gnu cross compiler (arm-xilinx-linux-gnueabi) include files such as features.h, posix_opt.h, and etc. I am not going to track down which truly defined the macro, but ASIO is the source which uses _POSIX_THREADS and so the linker option -pthread should be there.

    Again, non ASIO C++11 thread doesn't need -pthread for g++ 4.9.2 but standalone ASIO needs it. The following code is built correctly without -pthread in g++4.9.2 (Xilinx SDK which is based on Eclipse):

    #include <thread>
    void test() {
        for(int i=0;i<100;i++);
    }
    int main()
    {
        std::thread thread1(test);
        thread1.join();
        return 0;
    }
    
  • Splash
    Splash over 8 years
    I actually built a program without pthread using std::std just using -std=c++11
  • Zan Lynx
    Zan Lynx over 8 years
    @Splash: I get undefined reference to `pthread_create' if I try using std::thread without -pthread. You may be able to get away with using locks since glibc has a lock-free stub implementation that gets swapped out for the real one when you link libpthread.so
  • Splash
    Splash over 8 years
    Then why the application using ASIO can't be built without -lpthread, but application without ASIO can? Same compiler, same IDE, same linker options.
  • Mike Kinghan
    Mike Kinghan over 8 years
    You say you compiled your program with g++ 4.5.3 -std=c++11. The option -std=c++11 was only introduced in g++ 4.7. It is rejected by g++ 4.5.3. Live example: goo.gl/7Gmmlx As posted the main program will not compile with any C++ compiler or any options. To make your point you need to post example programs that will compile and link (or fail to) as written, on the OS that you specify, with the compiler version that you specify, with the verbatim compile and link commandlines that you specify.
  • Mike Kinghan
    Mike Kinghan over 8 years
    Thanks, that is helpful. Experiment by commenting out all the lines that relate to pthreads_create (3,13,14,15). Compile link and run. You'll see: terminate called after throwing an instance of 'std::system_error' what(): Enable multithreading to use std::thread: Operation not permitted Aborted (core dumped). To fix this, relink with -pthread.
  • Splash
    Splash over 8 years
    Thank you. So it could compile but couldn't run without -pthread.