Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

PYSAP as a Windows Service

Help
2007-09-10
2013-04-11
  • Hi there,

    I have created a RFC server as a windows service using PYSAP. Everything is 100%.....my only problem is that when I STOP the service it "hangs".

    I have tried killing the current process using the following:

    handle = win32api.OpenProcess(1, 0, os.getpid())
    win32api.TerminateProcess(handle, -1)         
    win32api.CloseHandle(handle)

    ....which does actually go from the task manager BUT the service does not stop properly.

    I have written out a log file on what is actually happening and it is because the RFC connection is not closing.....

    So I looked at the "pysap.py" code and see that it does a WHILE LOOP......so in MY code I do something like the following:

    while win32event.WaitForSingleObject(self.hWaitStop, 0) == win32event.WAIT_TIMEOUT:
                logger.debug("Entering NT event loop...")
                try:  
                    logger.debug("Before main loop...")
                    srv.main_loop(myargs)               
                    logger.debug("After main loop...")
                except pysap.SapRfcError,desc: 
                    ####

    And when I look at the log file AFTER I try STOP to service I can see that it hangs in the "main_loop" above....

    2007-09-10 11:49:15,467 - Logos_Log - DEBUG - Initialising logger...
    2007-09-10 11:49:15,467 - Logos_Log - DEBUG - Entering NT event loop...
    2007-09-10 11:49:15,467 - Logos_Log - DEBUG - Before main loop...

    Then I thought I could get a HANDLE on the current RFC connection by doing something like the following:

    myargs = ['d:\\rfc_server.py', '-a', 'PY_RFC_SERVER', '-g', '155.208.211.70', '-x', '3300']     
    args=' '.join(myargs[1:])
    handle=librfc.RfcAcceptExt(args)
    rc=librfc.RfcClose(handle)

    BUT that doesn't work at all...the handles would be different(I think)......the "main_loop" in the PYSAP module will not end.....

    Here is the "main_loop" code in the PYSAP module....

    def main_loop(self,argv):
            """Pass sys.argv as argument to this function."""
            import time
            args=' '.join(argv[1:])
            handle=librfc.RfcAcceptExt(args)
            err=0
            if handle==0:
                raise SapRfcError('connection failed')
            while 1:
                c_func_name=c.c_buffer(30)
                rc=librfc.RfcGetNameEx(handle,c.byref(c_func_name))
                if rc==0: # RFC_OK
                    func_name=c_func_name.value
                    if self.__funcs.has_key(func_name):
                        func_obj=self.__funcs[func_name](self.__rel4)
                        func_rc=func_obj.f(handle)
                        if func_rc:
                            break
                    else:
                        librfc.RfcAbort(handle,'Function %r not found' % func_name)
                        err=1
                        break
                elif rc==17: # RFC_SYSTEM_CALLED
                    continue
                elif rc==6: # RFC_CLOSED
                    break
                else: # Error
                    raise SapRfcError('RFC server error, rc = %d' % rc)
                time.sleep(1)
            if err==0: rc=librfc.RfcClose(handle)

    Does anyone have an idea how to "kill" the RFC server "elegantly"?

    Your help is greatly appreciated!

    Lynton

     
    • Hi,

      You will need the latest version of pysap from CVS (head) which supports the listen (non-blocking) and dispatch (blocking) methods in addition to main_loop. Here is a short snippet from my program:

              def SvcDoRun(self):
                  import servicemanager
                  servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                        servicemanager.PYS_SERVICE_STARTED,
                                        (self._svc_name_, ''))
                 
                  srv = pysap.RfcServer()
                  srv.register_func(QuerryServiceStatus)
                  srv.register_func(ChangeServiceStatus)
              # Open a connection (registered RFC server in this case)
                  handle = srv.connect(['', '-a', 'mcl.controller', '-g', '10.2.1.200', '-x', 'sapgw00'])
              # Start infinite loop
                  while 1:
                      rc = win32event.WaitForSingleObject(self.hWaitStop, 500)
              # Exit if service is stopped
                      if rc == win32event.WAIT_OBJECT_0:
                          break
              # Process single RFC call
              # NOTE: the call to listen method is non-blocking i.e. it returns immediately which is preferable
              # in this case (otherwise service would exit only after the call was made to the RFC server)
              # If you need blocking behaviour use srv.dispatch(handle) instead
                      srv.listen(handle)
                     
                  servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                                        servicemanager.PYS_SERVICE_STOPPED,
                                        (self._svc_name_, ''))

      HTH,
      Klavdij

       
    • Hi there,

      Thanks so much for your help.....I downloaded the latest version from CVS and have used the methods as you stated, it works like a dream ;-)

      BTW: Just curious to know how you would handle losing a connection to the SAP gateway while the service is running? I would assume you just catch the exception in the loop and carry on trying to connect to the gateway?

      Thanks again for your help!

      Lynton