I did post this to the twisted list but as I said in the original post, I think it is more a windows type issue than twisted.
What I am trying to work out is should I import twisted.reactor etc inside the thread start in SvcDoRUn or import it globally as one of the examples does. And then should I be calling the reactor.fromthread in the SvcStop function. If I import reactor in SvcDoRun will the SvcStop be called in the same thread or not. One of the examples import reactor globally, starts the reactor in SvcDoRun - inside the thread - and in SvcStop, calls the reactorfromthread. This to me implies that SvcStop is in a different thread to SvcDoRun. But I could be completely wrong on this point. As you can see I am a little bit confused about what is happening here. I have been looking for some info on running twisted as a Windows Service. I have found various examples in mailing-lists and blogs that vary in what seem to be important respects. I have included them below as 3 examples. The problem I have is working out which scheme or combination I should be adopting. I have tried out some of the options and they appear to work. But I need something better than seems to work. My gut reaction is that I should be putting all my imports into SvcDoRun, since they will be used in the thread. But if I import the reactor in SvcDoRun, should I be using reactor.callfromthread(reactor.stop). I think not I think the use of waitforobject is the right thing to do as well without fully understanding it at the moment. If anyone can throw some light on what to do I shall be very grateful. It could be that I should post this question to python-windows mailing list since it seems to me more pertinent to windows than twisted. Thanks for any info. John Aherne Here is 1st example. The reactor is imported globally not in SvcDoRun It uses the waitforobject to detect stopping the service The reactor.stop is calledfromthread [Twisted-Python] How to run Twisted as a service in Windows? Thomas Jacob jacob at internet24.de Wed Aug 9 10:49:30 EDT 2006 Previous message: [Twisted-Python] How to run Twisted as a service in Windows? Next message: [Twisted-Python] How to run Twisted as a service in Windows? Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] AFAIK, twistd doesn't provide direct support for Windows Services yet (Is this planned?). But you can easily wrap a reactor,run() yourself by doing something like the following using the Win32-Python packages import win32serviceutil import win32service import win32event from twisted.internet import reactor import sys class IMSAgentBase(win32serviceutil.ServiceFramework): _svc_name_ = "myService" _svc_display_name_ = "My little Service" _svc_description_ = "My little Service" # Win2k or later _svc_deps_ = ["RpcSs"] # Start after the Network has come up... def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) reactor.callFromThread(reactor.stop) win32event.SetEvent(self.hWaitStop) def SvcDoRun(self): # initialize your services here reactor.run() win32event.WaitForSingleObject(self.hWaitStop,win32event.INFINITE) def HandleCommandLine(cls): win32serviceutil.HandleCommandLine(cls) Run the above as a script. Here is the 2nd example. The imports are global not in SvcDoRun And the reactor .stop is not called from thread. And the wait for stop event is in a timeout loop It uses waitforobject events It sets installsignalhandlers to 0 You can then test it out with the sample Echo client from the core docs. """qotdservice.py Sample Twisted Windows Service """ # Service Utilities import win32serviceutil import win32service import win32event # Twisted imports from twisted.internet.protocol import Protocol, Factory from twisted.internet import reactor class QOTD(Protocol): def connectionMade(self): self.transport.write("An apple a day keeps the doctor away\r\n") self.transport.loseConnection() class WindowsService(win32serviceutil.ServiceFramework): _svc_name_ = "TwistedWin32Service" _svc_display_name_ = "Twisted Win32 Service" def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) def SvcDoRun(self): import servicemanager self.CheckForQuit() factory = Factory() factory.protocol = QOTD reactor.listenTCP(8007, factory) reactor.run(installSignalHandlers=0) def CheckForQuit(self): retval = win32event.WaitForSingleObject(self.hWaitStop, 10) if not retval == win32event.WAIT_TIMEOUT: # Received Quit from Win32 reactor.stop() reactor.callLater(1.0, self.CheckForQuit) if __name__=='__main__': win32serviceutil.HandleCommandLine(WindowsService) Here is the 3rd example. The imports are done in SvcDoRun. There is no callfrom thread It does not use the waitforobject import sys, os import win32serviceutil, win32service class MyService(win32serviceutil.ServiceFramework): """NT Service.""" _svc_name_ = "MyService" _svc_display_name_ = "MyService server" def SvcDoRun(self): import server f = open(os.path.join(server.rootPath, "cyberhigh.log"), 'a') from twisted.python.log import startLogging from twisted.application.app import startApplication from twisted.internet import reactor startLogging(f) startApplication(server.application, 0) reactor.run() def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) from twisted.internet import reactor reactor.stop() if __name__ == '__main__':</pre> win32serviceutil.HandleCommandLine(MyService)</pre>
_______________________________________________ python-win32 mailing list python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32