PYSAP as a Windows Service

Help
2007-09-10
2013-04-11
  • Nobody/Anonymous

    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

     
    • Klavdij Voncina

      Klavdij Voncina - 2007-09-10

      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

       
    • Nobody/Anonymous

      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

       

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks