Menu

#1107 Chain c++ server example double-close socket issue

v1.0 (example)
closed-fixed
None
5
2017-02-05
2017-02-03
diskonnect
No

In example (7.2.8 How to Chain C++ Server Classes to Accept Messages on the Same Port) https://www.genivia.com/doc/soapdoc2.html#tth_sEc7.2.8
there is an issue - if the request is processed not by the first object, then connection socket will be closed twice:

abc.accept(); <------- here we got our initial socket
...
if(soap_begin_serve(&abc)) <------- no error, so we taking else if branch
abc.soap_stream_fault(std::cerr);
else if (abc.dispatch() == SOAP_NO_METHOD) <------- request comes for another object, i.e. abc.dispatch() == SOAP_NO_METHOD)
{
soap_copy_stream(&uvw, &abc); <------- here we copy request data and socket, but original object (abc) still holds it.
if (uvw.dispatch() == SOAP_NO_METHOD) <------- request comes for another object, so again SOAP_NO_METHOD
{
soap_copy_stream(&xyz, &uvw); <------- here we copy request data and socket, but original object (uvw) still holds it.
if (xyz.dispatch()) <------- process request. At the end of the processing socket will be closed.
{
soap_send_fault(&xyz); // send fault to client
xyz.soap_stream_fault(std::cerr);
}
soap_free_stream(&xyz); // free the copy <------- mark socket as invalid
xyz.destroy(); <------- socket already closed and marked as invalid, so it won't be closed again
}
else
{
soap_send_fault(&uvw); // send fault to client
uvw.soap_stream_fault(std::cerr);
}
soap_free_stream(&uvw); // free the copy <------- mark socket as invalid
uvw.destroy(); <------- socket marked as invalid, so it won't be closed again
}
else
abc.soap_stream_fault(std::cerr);
abc.destroy(); <------- socket is closed by other object, but in this object it is not marked as closed. It will be closed again.

We can call soap_free_stream(&abc) before caling abc.destroy(), but in the case request is not processed by any object, we will have leaked socket descriptor.
For now we come up with solution - call soap_free_stream(&abc) if dispatch() method was successful. But documentation doesn't say anything about this case.
Can you please take a look? Possibly there is a need to change documentation, or somehow fix the double-close issue.

Originally found in 2.8.32, but don't see any changes in 2.8.42

Thanks,
Ivan.

Discussion

  • Robert van Engelen

    Good catch! This mechanism is not recommended, but of course should work without closing sockets twice. Best is to use soapcpp2 option -j, which makes sharing of soap contexts possible without having to copy context properties.

    Moving the soap_free_stream() calls right after the soap_copy_stream() calls should do the trick. Logically that makes sens (we need to verify):

    if (soap_begin_serve(&abc)) 
       abc.soap_stream_fault(std::cerr); 
    else if (abc.dispatch() == SOAP_NO_METHOD) 
    { 
       soap_copy_stream(&uvw, &abc); 
       soap_free_stream(&abc); // abc no longer uses this stream 
       if (uvw.dispatch() == SOAP_NO_METHOD) 
       { 
          soap_copy_stream(&xyz, &uvw); 
          soap_free_stream(&uvw); // uvw no longer uses this stream 
          if (xyz.dispatch()) 
          { 
             soap_send_fault(&xyz); // send fault to client 
             xyz.soap_stream_fault(std::cerr); 
          } 
          xyz.destroy(); 
       } 
       else
       { 
          soap_send_fault(&uvw); // send fault to client 
          uvw.soap_stream_fault(std::cerr); 
       } 
       uvw.destroy(); 
    } 
    else
       abc.soap_stream_fault(std::cerr); 
    abc.destroy(); 
    
     

    Last edit: Robert van Engelen 2017-02-03
  • Robert van Engelen

    • status: open --> pending-fixed
    • assigned_to: Robert van Engelen
     
  • Robert van Engelen

    • status: pending-fixed --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB