SimpleXMLRPCServer interruptable?

B

Bret

I'm coming back to Python after an absence and it's surprising how
many things I've forgotten since wandering (against my will) into Java
land.

Anyway, I have a need for a way to make SimpleXMLRPCServer
interruptable. Basically, I have a main server that, in response to
certain RPC calls, creates additional servers on different ports. I
then need to be able to shut these additional servers down.

I've got something like this in the __init__ of the class which
contains the spawned servers:

def __init__(self, host, port):
:
:
server = SimpleXMLRPCServer((host, port))
:
: Bunch of server.register_function calls
:
def serverWrapper():
try:
while True:
server.handle_request()
except:
pass

One of the methods that I register is:

def shutdown(self):
raise "Quitting time"

Through watching logs and such I can see that the shutdown() method is
getting called, but the loop isn't getting broken. I've done
something like this before in a previous job (so I don't have my
source in front of me, more's the pity) and am hoping someone can
chime in with a good idea.

Thanks in advance!


Bret Wortman
 
B

Bret

I just tried changing this so that I now have a threading.Event()
called self.done, which is set within the body of the shutdown()
method. The serverWrapper loop now looks like this:

def serverWrapper():
while True:
server.handle_request()
if self.done.isSet():
break

This works, but only if I follow the shutdown() rpc call a few seconds
later with ... something else to cause handle_request() to complete
again. Obviously, not quite the right approach....
 
G

Gabriel Genellina

I just tried changing this so that I now have a threading.Event()
called self.done, which is set within the body of the shutdown()
method. The serverWrapper loop now looks like this:

def serverWrapper():
while True:
server.handle_request()
if self.done.isSet():
break

This works, but only if I follow the shutdown() rpc call a few seconds
later with ... something else to cause handle_request() to complete
again. Obviously, not quite the right approach....

You could try setting a reasonable timeout on the listening socket; I
would override the server_bind method, calling self.socket.settimeout(xxx)
before calling the inherited method. I've never actually done it with a
SimpleXMLRPCServer, but *should* work. Don't use a very small timeout,
because it affects *all* subsequent operations.
 
E

Edward Kozlowski

You could try setting a reasonable timeout on the listening socket; I
would override the server_bind method, calling self.socket.settimeout(xxx)
before calling the inherited method. I've never actually done it with a
SimpleXMLRPCServer, but *should* work. Don't use a very small timeout,
because it affects *all* subsequent operations.

Try this:

def __init__(self, host, port):
self.done = False
server = SimpleXMLRPCServer((host, port))
:
: Bunch of server.register_function calls
:
def serverWrapper():
try:
while not self.done:
server.handle_request()
except:
pass

Your shutdown method becomes:

def shutdown(self):
self.done = True

HTH

-Edward Kozlowski
 
E

Edward Kozlowski

Try this:

def __init__(self, host, port):
self.done = False
server = SimpleXMLRPCServer((host, port))
:
: Bunch of server.register_function calls
:
def serverWrapper():
try:
while not self.done:
server.handle_request()
except:
pass

Your shutdown method becomes:

def shutdown(self):
self.done = True

HTH

-Edward Kozlowski

Sorry about the first post, I shot from the hip and had to make a few
more modifications to make it 'working' code. The example below works
fine for me.

import SimpleXMLRPCServer

class myServer:
def __init__(self, host, port):
self.done = False
self.server = SimpleXMLRPCServer.SimpleXMLRPCServer((host,
port))

def shutdown(self):
self.done = True
return 0

def getName(self):
return "Hey, I'm Ed"

def serverWrapper(self):
self.server.register_function(self.getName)
self.server.register_function(self.shutdown)
try:
while not self.done:
self.server.handle_request()
except:
pass


if __name__ == "__main__":
myServer('localhost', 6058).serverWrapper()

----0
 
B

Bret

Sorry about the first post, I shot from the hip and had to make a few
more modifications to make it 'working' code. The example below works
fine for me.

import SimpleXMLRPCServer

class myServer:
def __init__(self, host, port):
self.done = False
self.server = SimpleXMLRPCServer.SimpleXMLRPCServer((host,
port))

def shutdown(self):
self.done = True
return 0

def getName(self):
return "Hey, I'm Ed"

def serverWrapper(self):
self.server.register_function(self.getName)
self.server.register_function(self.shutdown)
try:
while not self.done:
self.server.handle_request()
except:
pass

if __name__ == "__main__":
myServer('localhost', 6058).serverWrapper()

---->>> s.getName()
"Hey, I'm Ed"

0

Thanks to all! I'm now keeping a file of my own snippets in hardcopy
so I won't lose them next time I change jobs. :)


Bret
 
B

Bret

Thanks to all! I'm now keeping a file of my own snippets in hardcopy
so I won't lose them next time I change jobs. :)

Bret

Oops, this actually misses part of the problem -- I need to construct
this server programmatically, so imbedding the call to start the
server in the "if __name__" construct doesn't work. If I start it
within the __init__, then the object that's creating it gets stuck
waiting for it to finish, which it never will. I need this to be
autonomous, which is why I was trying to do the start of the server in
a separate thread, but that doesn't seem to work either (that's what's
causing my process to need the second call; the thread completes the
loop and enters the next handle_request() call before the event or
boolean gets set).

Basically, I need a way for one server to start other autonomous
servers without waiting on them, and still retain the ability to shut
them down when their work is done.

Back to the keyboard. ;-)


Bret
 
B

Bret

Thanks to all! I'm now keeping a file of my own snippets in hardcopy
so I won't lose them next time I change jobs. :)

Bret

For completeness, what I ended up doing is this:

server = SimpleXMLRPCServer((host, port))
server.socket.settimeout(0.1)

ServerWrapper became:

def ServerWrapper():
while True:
try:
server.handle_request()
if self.done.isSet():
break
except timeout:
pass

And that seems to do the trick! Giving the socket a timeout allows me
to check the Event more frequently and catch the change within a
reasonable time.

Thanks again, Ed and Gabriel.


Bret
 
G

Gabriel Genellina

For completeness, what I ended up doing is this:

server = SimpleXMLRPCServer((host, port))
server.socket.settimeout(0.1)

ServerWrapper became:

def ServerWrapper():
while True:
try:
server.handle_request()
if self.done.isSet():
break
except timeout:
pass

And that seems to do the trick! Giving the socket a timeout allows me
to check the Event more frequently and catch the change within a
reasonable time.

Remember that the timeout applies to *all* socket operations; what if the
XML request requires more than 0.1s to read?
If handling large requests is more important than the delay at shutdown
time, consider raising that value.
 
B

Bret

En Thu, 06 Dec 2007 13:11:09 -0300, Bret <[email protected]> escribió:








Remember that the timeout applies to *all* socket operations; what if the
XML request requires more than 0.1s to read?
If handling large requests is more important than the delay at shutdown
time, consider raising that value.

Good point. Thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top