Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running SimpleXMLRPCServer in separate thread and shutting down

I have a class that I wish to test via SimpleXMLRPCServer in python. The way I have my unit test set up is that I create a new thread, and start SimpleXMLRPCServer in that. Then I run all the test, and finally shut down.

This is my ServerThread:

class ServerThread(Thread):
    running = True
    def run(self):
        self.server = #Creates and starts SimpleXMLRPCServer

        while (self.running):
            self.server.handle_request()

    def stop(self):
        self.running = False
        self.server.server_close()

The problem is, that calling ServerThread.stop(), followed by Thread.stop() and Thread.join() will not cause the thread to stop properly if it's already waiting for a request in handle_request. And since there doesn't seem to be any interrupt or timeout mechanisms here that I can use, I am at a loss for how I can cleanly shut down the server thread.

like image 366
Staale Avatar asked Feb 02 '09 08:02

Staale


2 Answers

I had the same problem and after hours of research i solved it by switching from using my own handle_request() loop to serve_forever() to start the server.

serve_forever() starts an internal loop like yours. This loop can be stopped by calling shutdown(). After stopping the loop it is possible to stop the server with server_close().

I don't know why this works and the handle_request() loop don't, but it does ;P

Here is my code:

from threading import Thread
from xmlrpc.server import SimpleXMLRPCServer
from pyWebService.server.service.WebServiceRequestHandler import WebServiceRquestHandler

class WebServiceServer(Thread):
    def __init__(self, ip, port):
        super(WebServiceServer, self).__init__()
        self.running = True
        self.server = SimpleXMLRPCServer((ip, port),requestHandler=WebServiceRquestHandler)
    self.server.register_introspection_functions()

    def register_function(self, function):
        self.server.register_function(function)

    def run(self):
        self.server.serve_forever()

    def stop_server(self):
        self.server.shutdown()
        self.server.server_close()

print("starting server")
webService = WebServiceServer("localhost", 8010)
webService.start()
print("stopping server")
webService.stop_server()
webService.join()
print("server stopped")
like image 53
szuuuken Avatar answered Nov 06 '22 06:11

szuuuken


Two suggestions.

Suggestion One is to use a separate process instead of a separate thread.

  • Create a stand-alone XMLRPC server program.

  • Start it with subprocess.Popen().

  • Kill it when the test is done. In standard OS's (not Windows) the kill works nicely. In Windows, however, there's no trivial kill function, but there are recipes for this.

The other suggestion is to have a function in your XMLRPC server which causes server self-destruction. You define a function that calls sys.exit() or os.abort() or raises a similar exception that will stop the process.

like image 1
S.Lott Avatar answered Nov 06 '22 07:11

S.Lott