Skip to content

Threads exit upon creation. #50

Closed
Closed

Description

@m-renaud

When running the server in gdb, I noticed that when using multiple threads, as soon as they are created they immediately exit, with the exception of the last one created. Here is the output of gdb when running your example hello_world.cpp:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
[New Thread 0x7ffff525e700 (LWP 9992)]
[Thread 0x7ffff525e700 (LWP 9992) exited]
[New Thread 0x7ffff4a5d700 (LWP 9993)]
[Thread 0x7ffff4a5d700 (LWP 9993) exited]
[New Thread 0x7ffff425c700 (LWP 9994)]
[Thread 0x7ffff425c700 (LWP 9994) exited]
[New Thread 0x7ffff3a5b700 (LWP 9995)]
[Thread 0x7ffff3a5b700 (LWP 9995) exited]
[New Thread 0x7ffff325a700 (LWP 9996)]

I was looking through the source code, specifically this loop (

for(int i = 0; i < num_threads; i++)
), and noticed that you are handling the creation of multiple threads within libhttpserver. I was under the impression that libmicrohttpd handled the thread pool with the MHD_USE_SELECT_INTERNALLY flag and setting MHD_OPTION_THREAD_POOL_SIZE in the options list (the va_args parameter to MHD_start_daemon).

I have verified that this is not an issue with my setup or libmicrohttpd by running the example in the libmicrohttpd docs with multiple threads, and they do not exit after creation.

If you need any more information, let me know!

Activity

  1. etr commented on May 1, 2014

    @etr
    Owner

    I was using libmicrohttpd internal select for long time before changing to the new implementation.
    This change (complication) is due to the desire to allow people using the library to implement comet mechanisms and introduce event listener (such as curl to implement proxies) much more easily.

    The main mistake here is not the overall implementation but that the "running" flag was set after the threads start and so almost all of them were exiting before the start completion.

    This is solved in the last code push. Sorry about this.

    I leave this open for a while so that you can notify me, if you want, on other related issues.

    Thanks!

  2. m-renaud commented on May 1, 2014

    @m-renaud
    Author

    Good News: The threads don't exit right away! :)

    Bad News: After this update the server segfaults when a request is received. Below is the output of gdb's backtrace when a request is made to the hello world example:

    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7ffff3a5a700 (LWP 9272)]
    0x0000000000000000 in ?? ()
    (gdb) bt
    #0  0x0000000000000000 in ?? ()
    #1  0x00007ffff7bb9aa7 in httpserver::webserver::finalize_answer(MHD_Connection*, httpserver::details::modded_request*, char const*) () from /usr/lib/libhttpserver.so.0
    #2  0x00007ffff7bba893 in httpserver::webserver::bodyless_requests_answer(MHD_Connection*, char const*, char const*, httpserver::details::modded_request*) () from /usr/lib/libhttpserver.so.0
    #3  0x00007ffff7bbaef5 in httpserver::webserver::answer_to_connection(void*, MHD_Connection*, char const*, char const*, char const*, char const*, unsigned long*, void**) () from /usr/lib/libhttpserver.so.0
    #4  0x00007ffff6dccd69 in ?? () from /usr/lib/libmicrohttpd.so.10
    #5  0x00007ffff6dce270 in ?? () from /usr/lib/libmicrohttpd.so.10
    #6  0x00007ffff6dd33e9 in MHD_run_from_select () from /usr/lib/libmicrohttpd.so.10
    #7  0x00007ffff6dd3691 in ?? () from /usr/lib/libmicrohttpd.so.10
    #8  0x00007ffff6dd324b in MHD_run () from /usr/lib/libmicrohttpd.so.10
    #9  0x00007ffff7bb3747 in httpserver::webserver::select(void*) () from /usr/lib/libhttpserver.so.0
    #10 0x00007ffff63b20a2 in start_thread () from /usr/lib/libpthread.so.0
    #11 0x00007ffff70c4d1d in clone () from /usr/lib/libc.so.6
    
  3. etr commented on May 2, 2014

    @etr
    Owner

    Sounds weird. Since I am currently running the hello_world example without any problem. Do you have any local change (library or example)? Would you be able to compile the library configuring it with the --enable-debug option so that you can have a more detailed stacktrace and sendd me which is the request you execute against the server on the example?

    Thanks

  4. m-renaud commented on May 2, 2014

    @m-renaud
    Author

    Recompiled with --enable-debug and reinstalled. I installed the library with make install as usual after configuring and building so that doesn't seem to be the issue, and I copied the hello_world example directly from the source tree. This is the backtrace:

    #0  0x0000000000000000 in ?? ()
    #1  0x00007ffff7b33f3a in httpserver::details::binders::functor_two<MHD_Response**, httpserver::webserver*, void>::operator() (this=0x7fffec009298, p1=0x7ffff51555d8, p2=0x7fffffffe450)
    at ../../libhttpserver/src/httpserver/binders.hpp:204
    #2  0x00007ffff7b297d8 in httpserver::webserver::finalize_answer (this=0x7fffffffe450, connection=0x7fffec0008c0, mr=0x7fffec008ab0, method=0x7fffec000a80 "GET") at ../../libhttpserver/src/webserver.cpp:1148
    #3  0x00007ffff7b2a2d9 in httpserver::webserver::complete_request (this=0x7fffffffe450, connection=0x7fffec0008c0, mr=0x7fffec008ab0, version=0x7fffec000a8b "HTTP/1.1", method=0x7fffec000a80 "GET")
    at ../../libhttpserver/src/webserver.cpp:1198
    #4  0x00007ffff7b277d2 in httpserver::webserver::bodyless_requests_answer (this=0x7fffffffe450, connection=0x7fffec0008c0, method=0x7fffec000a80 "GET", version=0x7fffec000a8b "HTTP/1.1", mr=0x7fffec008ab0)
    at ../../libhttpserver/src/webserver.cpp:889
    #5  0x00007ffff7b2a979 in httpserver::webserver::answer_to_connection (cls=0x7fffffffe450, connection=0x7fffec0008c0, url=0x7fffec000a84 "/hello", method=0x7fffec000a80 "GET", version=0x7fffec000a8b "HTTP/1.1", 
    upload_data=0x0, upload_data_size=0x7ffff5155978, con_cls=0x7fffec000918) at ../../libhttpserver/src/webserver.cpp:1284
    #6  0x00007ffff6cc5d69 in ?? () from /usr/lib/libmicrohttpd.so.10
    #7  0x00007ffff6cc7270 in ?? () from /usr/lib/libmicrohttpd.so.10
    #8  0x00007ffff6ccc3e9 in MHD_run_from_select () from /usr/lib/libmicrohttpd.so.10
    #9  0x00007ffff6ccc691 in ?? () from /usr/lib/libmicrohttpd.so.10
    #10 0x00007ffff6ccc24b in MHD_run () from /usr/lib/libmicrohttpd.so.10
    #11 0x00007ffff7b22719 in httpserver::webserver::select (self=0x6109f0) at ../../libhttpserver/src/webserver.cpp:324
    #12 0x00007ffff62ab0a2 in start_thread () from /usr/lib/libpthread.so.0
    #13 0x00007ffff6fbdd1d in clone () from /usr/lib/libc.so.6
    

    The request that I made was a GET request to http://localhost:8080/hello.

    I'm trying to think of something that could have gone wrong on my end but I can't think of anything :/

  5. m-renaud commented on May 2, 2014

    @m-renaud
    Author

    The segfault is a result of code changes in the last commit, checking out commit 24ae6ec doesn't segfault, so it appears to be the result of either the addition of the virtual destructor for http_response, or making the destructor of http_resource protected instead of public.

    Edit: On further examination, it's the virtual destructor that is causing the segfault.

  6. etr commented on May 2, 2014

    @etr
    Owner

    Cool, Do you have details about the virtual destructor causing this? It could help in fixing it since I am not being able to manifest the problem :(

  7. m-renaud commented on May 2, 2014

    @m-renaud
    Author

    I have tracked it down to the call _binder.get_mem_ptr() here

    return (_binder.exec()->*(_binder.get_mem_ptr()))(p1, p2);
    . It is returning nullptr for me, so it's segfaulting when nullptr is invoked for the pointer to member operator ->*.

    The bizarre thing is, if I remove the virtual from the http_response destructor at

    virtual ~http_response();
    , it no longer segfaults. The only thing that I can think of is that some of the stuff that is being done in converter with reinterpret_cast is possibly undefined behaviour and my specific compiler is handling it differently then yours :/

  8. etr commented on May 2, 2014

    @etr
    Owner

    Considering the implementation the virtual destructor is much more of a syntactic sugar in this case then else. Anyway this problem underlines that there are some weirdnesses in the implementation that I am not in love with. I will remove the virtual for now and continue to investigate on this since it seems utterly interesting from a language exploration perspective.
    Just as a curiosity, can you send me which is the compiler you are using and its version and send to me also the line you use to run the configure?

    Thanks!

  9. m-renaud commented on May 2, 2014

    @m-renaud
    Author

    I have tested it with g++ (GCC) 4.8.2 20140206 (prerelease), as well as clang version 3.4 (tags/RELEASE_34/final). I configured it with ../libhttpserver/configure --prefix=/usr.

  10. heinermann commented on May 2, 2014

    @heinermann

    I'm working with the same codebase as @mrenaud92 and I don't get the segfault.

    I've tried the following:
    g++ (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [trunk revision 209157]
    Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)

    I was unable to reproduce the error.

    There may be some kind of undefined behaviour involved which affects certain builds or systems. Either way we have no idea what is causing the issue.

    @mrenaud92 mentioned that it might be related to reinterpret_casts.

  11. etr commented on May 2, 2014

    @etr
    Owner

    It is strongly possible that it is an undefined behaviour.

    Honestly I think that the http_response implementation is over-complicated considered its goal. I will probably spend this days in removing all these specific response objects and creating just simple static factory methods inside the http_response object. It sounds like a much more simple and reasonable solution that will make the life easier for the compiler and for a reader/debugger of the code. I am sorry for the fact that this will probably break the backward compatibility.

  12. m-renaud commented on May 3, 2014

    @m-renaud
    Author

    Broken backwards compatibility isn't a big issue, it shouldn't take much time to change it over to the new API once it's finished.

  13. etr commented on May 11, 2014

    @etr
    Owner

    pushed out the new interface based on builder object.
    The http_response class is now non-modifiable by public code.

    I close this issue. Feel free to open an issue if you see any other problem.

    Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions