1

I'm using gSoap to write a webservice. It's running as a console application. In all gSoap examples I see, that requests are dispatched in infinite loop like for(;;;) even in multi-threaded version.

But how can I make my webservice to terminate gracefully when, say, user presses space on the console?

Preferably:

  1. stop accepting new connections;
  2. Serve existing ones;
  3. Exit from application
mpromonet
  • 11,326
  • 43
  • 62
  • 91
Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
  • are you looking for logic or sourcecode? – fazo Mar 25 '11 at 20:55
  • Anything that will help me to understand how to do that. Code preferred, but I'm not stupid and I think I will go well with just a word or two on the subject ;) For now I'm just break'ing from the loop on kbhit()=true and wait some seconds for requests to finish. But this is not reliable. What if some thread will take longer to finish? – Vladislav Rastrusny Mar 25 '11 at 20:59

3 Answers3

3

The only solution I came up so far is using timeouts soap->recv_timeout = 20; soap->send_timeout = 20; soap->connect_timeout = 5; soap->accept_timeout = 5; Then all blocking functions return periodically. But this is not ideal for me, because I want to be able to terminate the app quickly even if there is an ongoing transmission, but at the same time, don't want to compromise reliability on a slow/flaky connection (it's an embedded device connected via GPRS).

ilya
  • 31
  • 1
2

The section 7.2.4 How to Create a Multi-Threaded Stand-Alone Service in the documentation has example code for writing an accept loop. You need to write your own accept loop and add signal handling so it responds to Ctrl-C.

  1. stop accepting new connections:

    Leave the loop so you stop calling accept.

  2. Serve existing ones:

    The threads need to inform you when they are finished, so you can exit when the number of active clients is zero. (boost::thead_group has a join_all which does exactly that.)

  3. Exit from application:

Eddy Pronk
  • 6,527
  • 5
  • 33
  • 57
  • Unfortunately Eddy's solution doesn't work for me. soap_accept doesn't seem to exit on signal. I added select on soap.master before calling soap_accept. When a signal is received select will abort with EINTR which I can then pick up and use to exit the process. If select returns success then I just call soap_accept as before. HTH. – user2461592 Jun 20 '13 at 16:34
0

What you need to do is register signal handler so when you terminate your application using Ctrl + C, it calls you registered function where you can gracefully terminates.

e.g

class gsoap_test {

public:
   void start() {
     running_ = true;
     while(running_) {
       //gsoap threads
     }
     //stop and cleanup
   }


   void stop() {
        running_ = false;
   }
 private:
      bool running_;
};

 //global variable 
 gsoap_test gsoap;


void sighandler(int sig)
{
    std::cout<< "Signal caught..." << std::endl;

    //Stop gracefully here
    gsoap.stop();
    exit(0);

}

int main(int argc, char** argv) {

  //register signal
   signal(SIGABRT, &sighandler);
   signal(SIGTERM, &sighandler);
   signal(SIGINT, &sighandler);

   gsoap.start();

   return EXIT_SUCCESS;
}
rjoshi
  • 1,645
  • 1
  • 20
  • 31
  • Well, the question is how to gracefully terminate gSOAP threads, not just how to terminate application by CTRL-C or something. I'm terminating by checking kbhit now. – Vladislav Rastrusny Mar 26 '11 at 17:36
  • You can stop the threads in that function. I use same function for my muktithreading sip server where we need to gracefully stop the calls. – rjoshi Mar 26 '11 at 17:43
  • See the edits above where gsoap_test class is used. The object of gsoap_test can be passed as a function args to sighandler function as well if you don't want to make it global. Other option is to use boost::signal function. – rjoshi Mar 26 '11 at 18:06
  • 1
    Well, yes, but this is the same approach suggested by @Eddy Pronk, right? – Vladislav Rastrusny Mar 26 '11 at 18:09