Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.


#787 Crash in Curl_multi_handlePipeBreak

libcurl (354)

My application firstly adds two easy objects to the multi object and after that removes them.
Both easy-s share same connection. The connection is established before the easy-s are removed.
The crash occures on removal of the second easy. During removal the first easy, that was already removed, is found in the connection pipeline.

The fix should be, probably, removal of the easy from the connection pipeline.
The possible patch is attached.

Windows XP, curl-7.19.3-20081126

Memory of 0x00e851e0 was freed -> crash while accessing handle->multi

Crash Backtrace
IsPipeliningPossible(const SessionHandle * 0x00e851e0) line 2316 + 3 bytes
ConnectionExists(SessionHandle * 0x00e8d7c8, connectdata * 0x00e6a8d8, connectdata * * 0x0012f8f4) line 2460 + 9 bytes
create_conn(SessionHandle * 0x00e8d7c8, connectdata * * 0x003f2b74, Curl_dns_entry * * 0x0012fb24, unsigned char * 0x0012fb98) line 4294 + 23 bytes
Curl_connect(SessionHandle * 0x00e8d7c8, connectdata * * 0x003f2b74, unsigned char * 0x0012fb98, unsigned char * 0x0012fb9c) line 4480 + 21 bytes
multi_runsingle(Curl_multi * 0x003fe9e8, Curl_one_easy * 0x003f2b68) line 953 + 27 bytes
multi_socket(Curl_multi * 0x003fe9e8, unsigned char 0, unsigned int 4294967295, int 0, int * 0x0012fc60) line 1838 + 19 bytes
curl_multi_socket_action(void * 0x003fe9e8, unsigned int 4294967295, int 0, int * 0x0012fc60) line 1928 + 23 bytes
CurlTimerCB(void * 0x003fbb20, RvTimer * 0x0012fcd8) line 1966 + 24 bytes

Log snip
curl_multi_add_handle: easy_handle=0xe851e0, easy=0xe4fe20
curl_multi_remove_handle: easy_handle=0xe851e0, easy_conn=0xe500f8(size=1), state=12
curl_multi_add_handle: easy_handle=0xe6b028, easy=0xe6afa0
curl_multi_add_handle: easy_handle=0xe8d7c8, easy=0x3f2b68


  • I can see how it wants to remove the handle from the pipeline queues, but setting conn->readchannel_inuse and conn->writechannel_inuse explicitly to FALSE seems a bit weird. Can't the pipeline still be used by another handle?

  • Igor

    I doesn't understand the libcurl logic enough,
    therefore I just copied and pasted the "removal from pipeline" code from the Curl_done() :) The Curl_done() doesn't check if there are other requests in connection pipes.
    In my scenario after the problematic handle removal there was one more handle in pipeline, therefore You are probably rigth.

  • Ah, the *channel_inuse is just a flag saying that "someone" is using the channel right now so when it is set to FALSE another handle can grab it.

    I'll attach my somewhat edited version of your patch. I'll appreciate if you could try it and see if it still fixes the problem for you!

  • introduces and uses Curl_getoff_all_pipelines

  • Igor

    The patch works good!
    Thank you very much!

    Although I have one doubt.
    In ligth of your erlier remark regarding readchannel_inuse I think we should use

    if(Curl_removeHandleFromPipeline(data, conn->XXX_pipe) &&
    conn->XXXchannel_inuse && conn->XXX_pipe->size > 0)
    conn->XXXchannel_inuse = FALSE;

    instead of

    if(Curl_removeHandleFromPipeline(data, conn->XXX_pipe) &&
    conn->XXXchannel_inuse = FALSE;

    What do you think?

  • Thanks for the report, this problem is now fixed in CVS!

    • status: open --> closed-fixed