On 14/10/2011 7:47 PM, John Aherne wrote: ...
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.
Dunno - does the example work? If it does, then "yes" but if it doesn't, then "maybe not" :)
And then should I be calling the reactor.fromthread in the SvcStop function.
It has been a few years since I've used twisted, but I can't recall what that does.
If I import reactor in SvcDoRun will the SvcStop be called in the same thread or not.
Where you do the import doesn't impact this specific question; SvcStop will be almost certainly be called on a different thread than the main thread (ie, I'm pretty sure Windows itself always calls this on a different thread - python/pywin32/twisted have no say in this).
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.
You are correct - it will be a different thread. But I think that the "run" function will be called on the same thread as the module import, so exactly when you import the twisted stuff probably doesn't matter - it sounds like you are just looking for a way to stop the reactor from a different thread (ie, from the SvcStop thread)?
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.
Nope - the "top level" imports and the "run" function are almost certainly the same thread, and the "stop" function will be called on a thread created by Windows - but thread.get_ident() will tell you for sure.
Hope this helps - but if you still have problems, post the shortest possible thing that doesn't work as you expect and I might be able to help more...
Mark
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 <http://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
_______________________________________________ python-win32 mailing list python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32