Running SimpleXMLRPCServer in separate thread and shutting down

我与影子孤独终老i 提交于 2019-12-10 18:25:39

问题


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.


回答1:


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.




回答2:


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")



回答3:


This is my way. send SIGTERM to self. (Works for me)

Server code

import os
import signal
import xmlrpc.server

server = xmlrpc.server.SimpleXMLRPCServer(("0.0.0.0", 8000))
server.register_function(lambda: os.kill(os.getpid(), signal.SIGTERM), 'quit')
server.serve_forever()

Client code

import xmlrpc.client

c = xmlrpc.client.ServerProxy("http://localhost:8000")
try:
    c.quit()
except ConnectionRefusedError:
    pass


来源:https://stackoverflow.com/questions/502610/running-simplexmlrpcserver-in-separate-thread-and-shutting-down

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!