SimpleXMLRPCServer interruptable?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Bret

    SimpleXMLRPCServer interruptable?

    I'm coming back to Python after an absence and it's surprising how
    many things I've forgotten since wandering (against my will) into Java
    land.

    Anyway, I have a need for a way to make SimpleXMLRPCSer ver
    interruptable. Basically, I have a main server that, in response to
    certain RPC calls, creates additional servers on different ports. I
    then need to be able to shut these additional servers down.

    I've got something like this in the __init__ of the class which
    contains the spawned servers:

    def __init__(self, host, port):
    :
    :
    server = SimpleXMLRPCSer ver((host, port))
    :
    : Bunch of server.register _function calls
    :
    def serverWrapper() :
    try:
    while True:
    server.handle_r equest()
    except:
    pass

    One of the methods that I register is:

    def shutdown(self):
    raise "Quitting time"

    Through watching logs and such I can see that the shutdown() method is
    getting called, but the loop isn't getting broken. I've done
    something like this before in a previous job (so I don't have my
    source in front of me, more's the pity) and am hoping someone can
    chime in with a good idea.

    Thanks in advance!


    Bret Wortman
  • Bret

    #2
    Re: SimpleXMLRPCSer ver interruptable?

    I just tried changing this so that I now have a threading.Event ()
    called self.done, which is set within the body of the shutdown()
    method. The serverWrapper loop now looks like this:

    def serverWrapper() :
    while True:
    server.handle_r equest()
    if self.done.isSet ():
    break

    This works, but only if I follow the shutdown() rpc call a few seconds
    later with ... something else to cause handle_request( ) to complete
    again. Obviously, not quite the right approach....


    On Dec 5, 2:00 pm, Bret <bret.wort...@g mail.comwrote:
    I'm coming back to Python after an absence and it's surprising how
    many things I've forgotten since wandering (against my will) into Java
    land.
    >
    Anyway, I have a need for a way to make SimpleXMLRPCSer ver
    interruptable. Basically, I have a main server that, in response to
    certain RPC calls, creates additional servers on different ports. I
    then need to be able to shut these additional servers down.
    >
    I've got something like this in the __init__ of the class which
    contains the spawned servers:
    >
    def __init__(self, host, port):
    :
    :
    server = SimpleXMLRPCSer ver((host, port))
    :
    : Bunch of server.register _function calls
    :
    def serverWrapper() :
    try:
    while True:
    server.handle_r equest()
    except:
    pass
    >
    One of the methods that I register is:
    >
    def shutdown(self):
    raise "Quitting time"
    >
    Through watching logs and such I can see that the shutdown() method is
    getting called, but the loop isn't getting broken. I've done
    something like this before in a previous job (so I don't have my
    source in front of me, more's the pity) and am hoping someone can
    chime in with a good idea.
    >
    Thanks in advance!
    >
    Bret Wortman

    Comment

    • Gabriel Genellina

      #3
      Re: SimpleXMLRPCSer ver interruptable?

      En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wortman@g mail.comescribi ó:
      I just tried changing this so that I now have a threading.Event ()
      called self.done, which is set within the body of the shutdown()
      method. The serverWrapper loop now looks like this:
      >
      def serverWrapper() :
      while True:
      server.handle_r equest()
      if self.done.isSet ():
      break
      >
      This works, but only if I follow the shutdown() rpc call a few seconds
      later with ... something else to cause handle_request( ) to complete
      again. Obviously, not quite the right approach....
      You could try setting a reasonable timeout on the listening socket; I
      would override the server_bind method, calling self.socket.set timeout(xxx)
      before calling the inherited method. I've never actually done it with a
      SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
      because it affects *all* subsequent operations.

      --
      Gabriel Genellina

      Comment

      • Edward Kozlowski

        #4
        Re: SimpleXMLRPCSer ver interruptable?

        On Dec 5, 6:22 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
        En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wort...@g mail.comescribi ó:
        >
        I just tried changing this so that I now have a threading.Event ()
        called self.done, which is set within the body of the shutdown()
        method. The serverWrapper loop now looks like this:
        >
        def serverWrapper() :
        while True:
        server.handle_r equest()
        if self.done.isSet ():
        break
        >
        This works, but only if I follow the shutdown() rpc call a few seconds
        later with ... something else to cause handle_request( ) to complete
        again. Obviously, not quite the right approach....
        >
        You could try setting a reasonable timeout on the listening socket; I
        would override the server_bind method, calling self.socket.set timeout(xxx)
        before calling the inherited method. I've never actually done it with a
        SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
        because it affects *all* subsequent operations.
        >
        --
        Gabriel Genellina
        Try this:

        def __init__(self, host, port):
        self.done = False
        server = SimpleXMLRPCSer ver((host, port))
        :
        : Bunch of server.register _function calls
        :
        def serverWrapper() :
        try:
        while not self.done:
        server.handle_r equest()
        except:
        pass

        Your shutdown method becomes:

        def shutdown(self):
        self.done = True

        HTH

        -Edward Kozlowski

        Comment

        • Edward Kozlowski

          #5
          Re: SimpleXMLRPCSer ver interruptable?

          On Dec 5, 10:19 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
          On Dec 5, 6:22 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
          >
          >
          >
          En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wort...@g mail.comescribi ó:
          >
          I just tried changing this so that I now have a threading.Event ()
          called self.done, which is set within the body of the shutdown()
          method. The serverWrapper loop now looks like this:
          >
          def serverWrapper() :
          while True:
          server.handle_r equest()
          if self.done.isSet ():
          break
          >
          This works, but only if I follow the shutdown() rpc call a few seconds
          later with ... something else to cause handle_request( ) to complete
          again. Obviously, not quite the right approach....
          >
          You could try setting a reasonable timeout on the listening socket; I
          would override the server_bind method, calling self.socket.set timeout(xxx)
          before calling the inherited method. I've never actually done it with a
          SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
          because it affects *all* subsequent operations.
          >
          --
          Gabriel Genellina
          >
          Try this:
          >
          def __init__(self, host, port):
          self.done = False
          server = SimpleXMLRPCSer ver((host, port))
          :
          : Bunch of server.register _function calls
          :
          def serverWrapper() :
          try:
          while not self.done:
          server.handle_r equest()
          except:
          pass
          >
          Your shutdown method becomes:
          >
          def shutdown(self):
          self.done = True
          >
          HTH
          >
          -Edward Kozlowski
          Sorry about the first post, I shot from the hip and had to make a few
          more modifications to make it 'working' code. The example below works
          fine for me.

          import SimpleXMLRPCSer ver

          class myServer:
          def __init__(self, host, port):
          self.done = False
          self.server = SimpleXMLRPCSer ver.SimpleXMLRP CServer((host,
          port))

          def shutdown(self):
          self.done = True
          return 0

          def getName(self):
          return "Hey, I'm Ed"

          def serverWrapper(s elf):
          self.server.reg ister_function( self.getName)
          self.server.reg ister_function( self.shutdown)
          try:
          while not self.done:
          self.server.han dle_request()
          except:
          pass


          if __name__ == "__main__":
          myServer('local host', 6058).serverWra pper()

          ----
          >>s.getName()
          "Hey, I'm Ed"
          >>s.shutdown( )
          0

          Comment

          • Bret

            #6
            Re: SimpleXMLRPCSer ver interruptable?

            On Dec 5, 10:00 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
            On Dec 5, 10:19 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
            >
            >
            >
            On Dec 5, 6:22 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
            >
            En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wort...@g mail.comescribi ó:
            >
            I just tried changing this so that I now have a threading.Event ()
            called self.done, which is set within the body of the shutdown()
            method. The serverWrapper loop now looks like this:
            >
            def serverWrapper() :
            while True:
            server.handle_r equest()
            if self.done.isSet ():
            break
            >
            This works, but only if I follow the shutdown() rpc call a few seconds
            later with ... something else to cause handle_request( ) to complete
            again. Obviously, not quite the right approach....
            >
            You could try setting a reasonable timeout on the listening socket; I
            would override the server_bind method, calling self.socket.set timeout(xxx)
            before calling the inherited method. I've never actually done it with a
            SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
            because it affects *all* subsequent operations.
            >
            --
            Gabriel Genellina
            >
            Try this:
            >
            def __init__(self, host, port):
            self.done = False
            server = SimpleXMLRPCSer ver((host, port))
            :
            : Bunch of server.register _function calls
            :
            def serverWrapper() :
            try:
            while not self.done:
            server.handle_r equest()
            except:
            pass
            >
            Your shutdown method becomes:
            >
            def shutdown(self):
            self.done = True
            >
            HTH
            >
            -Edward Kozlowski
            >
            Sorry about the first post, I shot from the hip and had to make a few
            more modifications to make it 'working' code. The example below works
            fine for me.
            >
            import SimpleXMLRPCSer ver
            >
            class myServer:
            def __init__(self, host, port):
            self.done = False
            self.server = SimpleXMLRPCSer ver.SimpleXMLRP CServer((host,
            port))
            >
            def shutdown(self):
            self.done = True
            return 0
            >
            def getName(self):
            return "Hey, I'm Ed"
            >
            def serverWrapper(s elf):
            self.server.reg ister_function( self.getName)
            self.server.reg ister_function( self.shutdown)
            try:
            while not self.done:
            self.server.han dle_request()
            except:
            pass
            >
            if __name__ == "__main__":
            myServer('local host', 6058).serverWra pper()
            >
            ---->>s.getName()
            "Hey, I'm Ed"
            >s.shutdown()
            >
            0
            Thanks to all! I'm now keeping a file of my own snippets in hardcopy
            so I won't lose them next time I change jobs. :-)


            Bret

            Comment

            • Bret

              #7
              Re: SimpleXMLRPCSer ver interruptable?

              On Dec 6, 7:04 am, Bret <bret.wort...@g mail.comwrote:
              On Dec 5, 10:00 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
              >
              >
              >
              On Dec 5, 10:19 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
              >
              On Dec 5, 6:22 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
              >
              En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wort...@g mail.comescribi ó:
              >
              I just tried changing this so that I now have a threading.Event ()
              called self.done, which is set within the body of the shutdown()
              method. The serverWrapper loop now looks like this:
              >
              def serverWrapper() :
              while True:
              server.handle_r equest()
              if self.done.isSet ():
              break
              >
              This works, but only if I follow the shutdown() rpc call a few seconds
              later with ... something else to cause handle_request( ) to complete
              again. Obviously, not quite the right approach....
              >
              You could try setting a reasonable timeout on the listening socket; I
              would override the server_bind method, calling self.socket.set timeout(xxx)
              before calling the inherited method. I've never actually done it with a
              SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
              because it affects *all* subsequent operations.
              >
              --
              Gabriel Genellina
              >
              Try this:
              >
              def __init__(self, host, port):
              self.done = False
              server = SimpleXMLRPCSer ver((host, port))
              :
              : Bunch of server.register _function calls
              :
              def serverWrapper() :
              try:
              while not self.done:
              server.handle_r equest()
              except:
              pass
              >
              Your shutdown method becomes:
              >
              def shutdown(self):
              self.done = True
              >
              HTH
              >
              -Edward Kozlowski
              >
              Sorry about the first post, I shot from the hip and had to make a few
              more modifications to make it 'working' code. The example below works
              fine for me.
              >
              import SimpleXMLRPCSer ver
              >
              class myServer:
              def __init__(self, host, port):
              self.done = False
              self.server = SimpleXMLRPCSer ver.SimpleXMLRP CServer((host,
              port))
              >
              def shutdown(self):
              self.done = True
              return 0
              >
              def getName(self):
              return "Hey, I'm Ed"
              >
              def serverWrapper(s elf):
              self.server.reg ister_function( self.getName)
              self.server.reg ister_function( self.shutdown)
              try:
              while not self.done:
              self.server.han dle_request()
              except:
              pass
              >
              if __name__ == "__main__":
              myServer('local host', 6058).serverWra pper()
              >
              ---->>s.getName()
              "Hey, I'm Ed"
              >>s.shutdown( )
              >
              0
              >
              Thanks to all! I'm now keeping a file of my own snippets in hardcopy
              so I won't lose them next time I change jobs. :-)
              >
              Bret
              Oops, this actually misses part of the problem -- I need to construct
              this server programmaticall y, so imbedding the call to start the
              server in the "if __name__" construct doesn't work. If I start it
              within the __init__, then the object that's creating it gets stuck
              waiting for it to finish, which it never will. I need this to be
              autonomous, which is why I was trying to do the start of the server in
              a separate thread, but that doesn't seem to work either (that's what's
              causing my process to need the second call; the thread completes the
              loop and enters the next handle_request( ) call before the event or
              boolean gets set).

              Basically, I need a way for one server to start other autonomous
              servers without waiting on them, and still retain the ability to shut
              them down when their work is done.

              Back to the keyboard. ;-)


              Bret

              Comment

              • Bret

                #8
                Re: SimpleXMLRPCSer ver interruptable?

                On Dec 6, 7:04 am, Bret <bret.wort...@g mail.comwrote:
                On Dec 5, 10:00 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
                >
                >
                >
                On Dec 5, 10:19 pm, Edward Kozlowski <ekozlows...@gm ail.comwrote:
                >
                On Dec 5, 6:22 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
                >
                En Wed, 05 Dec 2007 18:20:35 -0300, Bret <bret.wort...@g mail.comescribi ó:
                >
                I just tried changing this so that I now have a threading.Event ()
                called self.done, which is set within the body of the shutdown()
                method. The serverWrapper loop now looks like this:
                >
                def serverWrapper() :
                while True:
                server.handle_r equest()
                if self.done.isSet ():
                break
                >
                This works, but only if I follow the shutdown() rpc call a few seconds
                later with ... something else to cause handle_request( ) to complete
                again. Obviously, not quite the right approach....
                >
                You could try setting a reasonable timeout on the listening socket; I
                would override the server_bind method, calling self.socket.set timeout(xxx)
                before calling the inherited method. I've never actually done it with a
                SimpleXMLRPCSer ver, but *should* work. Don't use a very small timeout,
                because it affects *all* subsequent operations.
                >
                --
                Gabriel Genellina
                >
                Try this:
                >
                def __init__(self, host, port):
                self.done = False
                server = SimpleXMLRPCSer ver((host, port))
                :
                : Bunch of server.register _function calls
                :
                def serverWrapper() :
                try:
                while not self.done:
                server.handle_r equest()
                except:
                pass
                >
                Your shutdown method becomes:
                >
                def shutdown(self):
                self.done = True
                >
                HTH
                >
                -Edward Kozlowski
                >
                Sorry about the first post, I shot from the hip and had to make a few
                more modifications to make it 'working' code. The example below works
                fine for me.
                >
                import SimpleXMLRPCSer ver
                >
                class myServer:
                def __init__(self, host, port):
                self.done = False
                self.server = SimpleXMLRPCSer ver.SimpleXMLRP CServer((host,
                port))
                >
                def shutdown(self):
                self.done = True
                return 0
                >
                def getName(self):
                return "Hey, I'm Ed"
                >
                def serverWrapper(s elf):
                self.server.reg ister_function( self.getName)
                self.server.reg ister_function( self.shutdown)
                try:
                while not self.done:
                self.server.han dle_request()
                except:
                pass
                >
                if __name__ == "__main__":
                myServer('local host', 6058).serverWra pper()
                >
                ---->>s.getName()
                "Hey, I'm Ed"
                >>s.shutdown( )
                >
                0
                >
                Thanks to all! I'm now keeping a file of my own snippets in hardcopy
                so I won't lose them next time I change jobs. :-)
                >
                Bret
                For completeness, what I ended up doing is this:

                server = SimpleXMLRPCSer ver((host, port))
                server.socket.s ettimeout(0.1)

                ServerWrapper became:

                def ServerWrapper() :
                while True:
                try:
                server.handle_r equest()
                if self.done.isSet ():
                break
                except timeout:
                pass

                And that seems to do the trick! Giving the socket a timeout allows me
                to check the Event more frequently and catch the change within a
                reasonable time.

                Thanks again, Ed and Gabriel.


                Bret

                Comment

                • Gabriel Genellina

                  #9
                  Re: SimpleXMLRPCSer ver interruptable?

                  En Thu, 06 Dec 2007 13:11:09 -0300, Bret <bret.wortman@g mail.comescribi ó:
                  For completeness, what I ended up doing is this:
                  >
                  server = SimpleXMLRPCSer ver((host, port))
                  server.socket.s ettimeout(0.1)
                  >
                  ServerWrapper became:
                  >
                  def ServerWrapper() :
                  while True:
                  try:
                  server.handle_r equest()
                  if self.done.isSet ():
                  break
                  except timeout:
                  pass
                  >
                  And that seems to do the trick! Giving the socket a timeout allows me
                  to check the Event more frequently and catch the change within a
                  reasonable time.
                  Remember that the timeout applies to *all* socket operations; what if the
                  XML request requires more than 0.1s to read?
                  If handling large requests is more important than the delay at shutdown
                  time, consider raising that value.

                  --
                  Gabriel Genellina

                  Comment

                  • Bret

                    #10
                    Re: SimpleXMLRPCSer ver interruptable?

                    On Dec 6, 7:43 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.a rwrote:
                    En Thu, 06 Dec 2007 13:11:09 -0300, Bret <bret.wort...@g mail.comescribi ó:
                    >
                    >
                    >
                    For completeness, what I ended up doing is this:
                    >
                    server = SimpleXMLRPCSer ver((host, port))
                    server.socket.s ettimeout(0.1)
                    >
                    ServerWrapper became:
                    >
                    def ServerWrapper() :
                    while True:
                    try:
                    server.handle_r equest()
                    if self.done.isSet ():
                    break
                    except timeout:
                    pass
                    >
                    And that seems to do the trick! Giving the socket a timeout allows me
                    to check the Event more frequently and catch the change within a
                    reasonable time.
                    >
                    Remember that the timeout applies to *all* socket operations; what if the
                    XML request requires more than 0.1s to read?
                    If handling large requests is more important than the delay at shutdown
                    time, consider raising that value.
                    >
                    --
                    Gabriel Genellina
                    Good point. Thanks!

                    Comment

                    Working...