4

Below is the framework for the windows service that I am running. In the event of an error, the error is logged and can be viewed in the event viewer. The problem is that the script just quits and does not restart again even though I have the recovery set to restart the service on the first, second and subsequent failures. Currently I have little error handling because I want to see what errors that may arise in the event viewer so that I can write code to handle these errors accordingly.

from win32api import CloseHandle, GetLastError, SetConsoleCtrlHandler
import os
import sys 
import time
import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "my_service_name"
    _svc_display_name_ = "my service"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        SetConsoleCtrlHandler(lambda x: True, True)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.run = True
        self.main()

    def main(self):
        while self.run == True
            pass          

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

Edit:

I tried to try: except around self.main but the outcome was still the same. The service did not restart when it crashed... Please anyone out there with any ideas? A service is not all that useful if it cannot restart in the event of a crash... Might as well run it as a .pyc

Edit:

below is an example of an error that may arise within my script... I don't believe this error message is particularly useful because what I am try to achieve is to have the service restart but none the less here is an example of an error that has crashed my service without it restarting:

The instance's SvcRun() method failed 
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\win32\lib\win32serviceutil.py", line 806, in SvcRun
    self.SvcDoRun()
  File "C:\Some_Service.py", line 46, in SvcDoRun
    self.main()
  File "Some_Service.py", line 61, in main
    ser = self.open_serial_port()
  File "Some_Service.py", line 70, in open_serial_port
    serial_connection.open()
  File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 56, in open
    raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))
SerialException: could not open port COM6: [Error 1225] The remote system refused the network connection. 
%2: %3
Richard
  • 15,152
  • 31
  • 85
  • 111
  • What is the error that's causing it to Crash? Aside from not sleeping in main() your code looks serviceable. – AlG Mar 22 '11 at 12:21
  • @qor72 This is just the framework to make a script a service. The script I am running is used to parse serial data. Problem is that there could be a number of errors that happen, for example the service might not be able to connect to my database. What I would like for now is it to sleep for a few seconds and restart the service again. I am not sure why it should die and not restart if I have the service setting to restart on failure.. I must be missing a section of code somewhere to handle that? – Richard Mar 22 '11 at 12:30
  • In the services I've written, not in Python, the error checking writes the error to the log and continues without requiring a restart. That's why I'm curious about your message; for example, is it that the service can't write to the error log and that's causing a bug that's wrecking your service? – AlG Mar 22 '11 at 12:58
  • @qor72 I just figured it out... Answer here gave me some insight. http://stackoverflow.com/questions/220382/how-can-a-windows-service-programmatically-restart-itself . so in python I would need to do a os._exit(1) or some exit that is not zero. BiggAl's answer was close but was missing the os._exit(-1) instead of return -1 – Richard Mar 22 '11 at 13:05

3 Answers3

8

Below is a service that just divides by zero to raise an error. If there is an error, an event is sent and the service exits using os._exit(-1). The value has to be anything but 0 so that the windows knows that the service didn't exit nicely.

from win32api import CloseHandle, GetLastError, SetConsoleCtrlHandler
import os
import sys
import time

import win32serviceutil
import win32service
import win32event
import servicemanager

import traceback



class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "test"
    _svc_display_name_ = "test"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        SetConsoleCtrlHandler(lambda x: True, True)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)




    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False
    def SvcDoRun(self):

        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.run = True
        try: # try main
            self.main()
        except:
            servicemanager.LogErrorMsg(traceback.format_exc()) # if error print it to event log
            os._exit(-1)#return some value other than 0 to os so that service knows to restart


    def main(self):

        while self.run == True:
            time.sleep(30)         
            t = 1/0

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)
Richard
  • 15,152
  • 31
  • 85
  • 111
0

My suspicion is that your service is not in fact crashing, but completing before it has a chance to run. Have you tried inserting a sleep statement of a few seconds in the main function?

theheadofabroom
  • 20,639
  • 5
  • 33
  • 65
  • The main function is an infinite loop until the service get's the stop command. The script is in fact crashing because the error that caused the crash is logged. I want the service to restart if there is an error... – Richard Mar 18 '11 at 13:44
  • What is your error message? Is it possible that while it's crashing out it's still returning an errorcode of 0? maybe you need something along the lines of: `try:\n main()\nexcept:\n return -1` – theheadofabroom Mar 18 '11 at 13:56
0

Why don't you use a try-except for it ?

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "my_service_name"
    _svc_display_name_ = "my service"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        SetConsoleCtrlHandler(lambda x: True, True)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.run = True
        self.main()

    def main(self):
        while self.run == True
            try :
                <your code>
            except :
                time.sleep(3)
                <may be an error log here>



if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)
philnext
  • 3,242
  • 5
  • 39
  • 62