[python-win32] windows service problem and twisted

John Aherne johnaherne at rocs.co.uk
Fri Oct 14 22:45:12 CEST 2011


On Fri, Oct 14, 2011 at 12:51 PM, Mark Hammond <skippy.hammond at 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 at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-win32/attachments/20111014/939ad8c7/attachment-0001.html>


More information about the python-win32 mailing list