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.
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
soapcontexts possible without having to copy context properties.Moving the
soap_free_stream()calls right after thesoap_copy_stream()calls should do the trick. Logically that makes sens (we need to verify):Last edit: Robert van Engelen 2017-02-03