On Fri, Oct 14, 2011 at 12:51 PM, Mark Hammond <skippy.hamm...@gmail.com>wrote:
> 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<http://mail.python.org/mailman/listinfo/python-win32> >> > > Mark Thanks for the response Yes you spotted what I wanted to do but didn't spell out. I want to stop the reactor from the thread in SvcStop. It helped clarify my thoughts. What I found was that I could stop the reactor whether I used callfromthread or not. It all worked regardless. What concerned me was that I wasn't sure that SvcStop was running in another thread. Now I know it is and because the reactor is not threadsafe, I should use callfromthread to be really sure and to avoid possible future problems. So thanks, but if I run into more problems I may have to come back with other questions. John Aherne
_______________________________________________ python-win32 mailing list python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32