I have a multi-threaded gSOAP service running with enabled http-keepalive. How can I gracefully shutdown the service when there are still clients connected?
A similar question was asked in gSoap: how to gracefully shutdown the webservice application?, but the answers do not cover the http-keepalive aspect: The soap-serve function will simply not return until the http-keepalive-session wasn’t closed by the client. Thus, step 2 in the accepted answer will block until the client decides to close the connection (or the receive-timeout expires, but a short timeout would break the desired http-keepalive behaviour here).
The examples from the gSOAP documentation suffer from the same problem.
What I tried so far was to call soap_done() for all soap structs that are hanging in a soap_serve call from the main thread to interrupt the connections waiting for http-keepalive, which works most of the time, but crashes in rare conditions (a race condition maybe), so this is no solution for me.
I just ran into the very same problem and I think I’ve got a solution for you.
As you just said, the problem is that the gSoap hangs on soap_serve. This happens because gSOAP generates an internal loop for you that waits for the arrival of all keep-alive requests OR a timeout on the server-side arises.
What I’ve done is grabbing the soap_serve function inside the automatically generated service stub. I’m going to list the original soap_serve function so that you can find it on your service stub file :
You should extract the body of this function and replace your old soap_serve(mySoap) call inside your thread (the thread that performs the requests and hagns because of the keep-alive) with the following:
Note the following:
But we are not done yet, thanks to what AudioComplex pointed out, the system still remains waiting for reqeuests on soap_begin_recv. But I’ve got a solution for that too 😉
Each of the threads on the connection-handling pool creates a copy of the main soap context (via soap_copy), these threads are the ones that
I store each of these contexts as an element on the array that resides on the main connection-handling thread.
When terminating the main connection-handling thread (the one that serves the requests) it will go through all soap contexts and finalize “manually” the connection by using:
This will force the soap_serve loop to finish. It actually will stop the internal loop near line 921 of stdsoap2.cpp_
It is not the cleanest solution (haven’t found a cleaner one) but it will definitely stop the service.