Jacob Gabrielson wrote:
Hi,
Has anyone run into a problem where their Twisted application gets a SIGBREAK and shuts down, on Windows? I have a simple application using the ReconnectingClientFactory, running as a service (via srvany.exe), that occasionally dies with a few messages:
2006/09/24 16:46 Pacific Daylight Time [-] Received SIGBREAK, shutting down. 2006/09/24 16:46 Pacific Daylight Time [AgentProtocol,client] <twisted.internet.tcp.Connector instance at 0x00A1B468> will retry in 2 seconds 2006/09/24 16:46 Pacific Daylight Time [AgentProtocol,client] Stopping factory <twisted.internet.protocol.ReconnectingClientFactory instance at 0x00A10D28> 2006/09/24 16:46 Pacific Daylight Time [-] Main loop terminated.
There's not a lot to go on, but I'm wondering if this is something anyone else has run into on Windows. I'm not really sure how a SIGBREAK could get generated there in the first place.
You may receive that signal when users log off. I'm using the following code to ignore signals when running as service (but I'm also using the win32serviceutil module to start as a service). import win32api def sighandler(sig): print "received signal %s" % (sig,) return True win32api.SetConsoleCtrlHandler(sighandler, True) However, I guess that if you're using that code unchanged you might not be able to stop your service anymore. More Information can be found at msdn: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/bas... You might also want to look into using the win32service module. IMHO, it's a lot easier to handle than srvany. I'm attaching our nbsvc program as example, which we use to start our programs as NT services. Regards, - Ralf #! /usr/bin/env python import unbuffered import warnings warnings.filterwarnings("ignore", "the FCNTL module is deprecated; please use fcntl") warnings.filterwarnings("ignore", "the TERMIOS module is deprecated; please use termios") import os import sys import servicemanager import win32serviceutil import win32service import win32api from twisted.internet import reactor from twisted.python import log, logfile def sighandler(sig): print "received signal %s" % (sig,) return True win32api.SetConsoleCtrlHandler(sighandler, True) class NBService(win32serviceutil.ServiceFramework): _svc_name_ = "" _svc_display_name_ = "" def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.args = args def slog(self, x): servicemanager.LogMsg( servicemanager.EVENTLOG_INFORMATION_TYPE, x, (self._svc_name_, '') ) def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) try: self.slog(servicemanager.PYS_SERVICE_STOPPING) except Exception, err: print "Error while trying to log service event in SvcStop: %s" %(err,) from twisted.internet import reactor reactor.callFromThread(reactor.stop) # SvcStop only gets triggered when the user explictly stops (or restarts) # the service. To shut the service down cleanly when Windows is shutting # down, we also need to hook SvcShutdown. SvcShutdown = SvcStop def SvcDoRun(self): self.slog(servicemanager.PYS_SERVICE_STARTING,) reactor.callLater(0.0, self.slog, servicemanager.PYS_SERVICE_STARTED) oldrun = reactor.run def reactor_run(): return oldrun(installSignalHandlers=False) reactor.run = reactor_run try: self.main() try: self.slog(servicemanager.PYS_SERVICE_STOPPED) except Exception, err: print "Error while trying to log service event in SvcDoRun: %s" %(err,) print "done" print "-"*70 except Exception, err: print "FATAL ERROR:", err import traceback traceback.print_exc() raise def usage(s=None): if s: print "nbsvc: error parsing command line: %s" % (s,) print print "Usage:" print "nbsvc install NAME CMD [ARG1...]" print " register service with service manager" print print "nbsvc remove NAME" print " unregister service at service manager" print print "nbsvc start NAME" print " start registered service" print print "nbsvc stop" print " stop running service" print sys.exit(10) class Main(object): def __init__(self): self.evtsrc_dll = os.path.abspath(servicemanager.__file__) self.klass = NBService #if servicemanager.RunningAsService(): # return if len(sys.argv)<3: usage() cmd = sys.argv[1] name = sys.argv[2] args = sys.argv[3:] self.name = name self.args = args self.klass._svc_name_ = name self.klass._svc_display_name_ = name try: m=getattr(self, "cmd_"+cmd) except AttributeError: usage("unknown command '%s'" % cmd) m(args) def cmd_install(self, args): assert getattr(sys, 'frozen', False), "must be run in frozen mode" arg0 = os.path.basename(args[0]) if arg0.lower().endswith('.exe'): arg0 = arg0[:-4] args[0] = arg0 __import__('__main__%s__' % arg0) k=self.klass win32serviceutil.InstallService(None, serviceName=k._svc_name_, displayName=k._svc_display_name_, startType=win32service.SERVICE_AUTO_START, exeName=sys.executable, exeArgs='run %s %s' % (self.name, " ".join(['"%s"' % x for x in args])), ) sys.exit(0) def cmd_stop(self, arg): win32serviceutil.StopService(self.klass._svc_name_) def cmd_remove(self, arg): win32serviceutil.RemoveService(self.klass._svc_name_) def cmd_start(self, arg): win32serviceutil.StartService(self.klass._svc_name_) def cmd_run(self, arg): #log.startLogging(open(r"c:\log.txt", 'wb')) sys.argv[1:] = arg[1:] k=self.klass iname = "__main__%s__" % (arg[0],) def main(self): __import__(iname).main() k.main = main # __import__(iname).main servicemanager.Initialize(k._svc_name_, self.evtsrc_dll) servicemanager.PrepareToHostSingle(k) servicemanager.StartServiceCtrlDispatcher() if __name__=='__main__': Main()