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

Reply via email to