6 Replies Latest reply on Sep 18, 2007 11:38 PM by Trustin Lee

    Interruption and the Remoting 3 API

    David Lloyd Master

      Some operations in Remoting 3 might be long-running under normal conditions, and thus it is be desirable to provide a means to interrupt them. This is means is provided by way of allowing the synchronous request methods (and, of course, the methods on Future) to throw InterruptedException. Examples are in the Context, FutureReply, and ReplyContext interfaces.

      However there are also methods that may not be long-running under normal circumstances, but might run long under conditions such as network connection problems or heavily loaded servers. Such methods include the transaction control methods (begin/commit/rollback and the XAResource implementation), and probably a few others as well.

      So here's the question: should these normally-quick-but-possibly-sometimes-slow methods:
      a) throw InterruptedException,
      b) translate the InterruptedException into a RemotingException (and keep the thread's interruption status set),
      or c) just run uninterruptably (and propagate the thread's interruption status)?

      Right now the code is a mishmash of all three. :-)

      The advantage of (a) is that the user's code can be the most "correct" in its handling of interruption. Which is to say, interruption stops execution (more or less) immediately, and is easy to detect. On the other hand, it is pretty unlikely that it will happen, and if there's one good way to annoy users, it is to make them write handlers for things that don't happen often.

      Option (b) has the advantage of being simpler to code for the user. The operation is still stopped immediately. But it's harder now to figure out that it was due to interruption. Probably the user will never even consider that possibility. I don't know if this is a disadvantage in *practical* terms though.

      Option (c) is the easiest of all for the user - but it makes it impossible for the user to stop the operation using interruption, in the unlikely event that it runs long.

        • 1. Re: Interruption and the Remoting 3 API
          Trustin Lee Apprentice

          If the invocation is interrupted by Thread.interrupt(), throwing InterruptedException would be reasonable, but as you pointed out, it's painful to take care of another catch block.

          We could provide both interruptable and uninterruptable invocation methods; invoke and invokeUninterruptably (or invoke and invokeInterruptably) Then user could choose what they want.

          What confuses me though is if we are talking about the InterruptedException raised by Thread.interrupt() or any other interruption caused by means such as cancellation request for the invocation. Or are they treated as the same thing? Do we need to discriminate these two cases?

          I'd prefer to have a subclass of RemotingException (e.g. CancelledInvocationException) if we need discrimination. Users can deal with the interruption when they really want to do. This will also help users to find out if its interrupted by Thread.interrupt(), any system signal or request for cancellation from the type of the raised exception.

          Users will not consider the possibility of the interrupted invocation at all at the first time, but they will start to consider once they see the exception log, so I think it's not a big deal.

          • 2. Re: Interruption and the Remoting 3 API
            David Lloyd Master

             

            "trustin" wrote:
            We could provide both interruptable and uninterruptable invocation methods; invoke and invokeUninterruptably (or invoke and invokeInterruptably) Then user could choose what they want.


            Yeah, that's an option (d). I was hesitant to mention that due to the potential for massive API clutter, but that is an option as well.

            "trustin" wrote:
            What confuses me though is if we are talking about the InterruptedException raised by Thread.interrupt() or any other interruption caused by means such as cancellation request for the invocation. Or are they treated as the same thing? Do we need to discriminate these two cases?


            We're talking about Thread.interrupt() on the local side's blocking thread. If an operation is cancelled or interrupted on the remote side, it will get a RemotingException on the local side. The reason for this is that the proper behavior for an thread that catches InterruptedException is to either handle the interruption (if you are the owner of the thread), or propagate it. And I wouldn't want to falsely propagate thread interruption if I'm not in control of the thread's interruption policy. Does that make sense?

            "trustin" wrote:
            I'd prefer to have a subclass of RemotingException (e.g. CancelledInvocationException) if we need discrimination. Users can deal with the interruption when they really want to do. This will also help users to find out if its interrupted by Thread.interrupt(), any system signal or request for cancellation from the type of the raised exception.


            There is a well-defined protocol for how interruption must be handled (check out http://jcip.net/ for more info). For interruption, our two options are to throw InterruptedException, or propagate the thread's interruption flag.


            • 3. Re: Interruption and the Remoting 3 API
              David Lloyd Master

               

              "david.lloyd@jboss.com" wrote:
              The reason for this is that the proper behavior for an thread that catches InterruptedException is to either handle the interruption (if you are the owner of the thread), or propagate it. And I wouldn't want to falsely propagate thread interruption if I'm not in control of the thread's interruption policy. Does that make sense?


              Let me clarify further - it can never be proper behavior to interrupt a thread based on the interruption of a remote thread. A thread should only be interrupted if the interrupting method is in control of that thread's interruption policy. The interrupter of the remote thread is very unlikely to have control over the local thread's interruption policy.

              • 4. Re: Interruption and the Remoting 3 API
                Jason Greene Master

                 

                "david.lloyd@jboss.com" wrote:
                Some operations in Remoting 3 might be
                So here's the question: should these normally-quick-but-possibly-sometimes-slow methods:
                a) throw InterruptedException,
                b) translate the InterruptedException into a RemotingException (and keep the thread's interruption status set),
                or c) just run uninterruptably (and propagate the thread's interruption status)?


                IMO I like option A for everything that is obviously I/O, and option B for anything very high-level, but using a subclassed exception in case someone wants to handle it still.

                -Jason

                • 5. Re: Interruption and the Remoting 3 API
                  David Lloyd Master

                  One consequence of using a RemotingException subclass is that, unlike when using InterruptedException, the thread must be re-interrupted before throwing the exception. So user code that doesn't check for it, will be interrupted at the next interruptable point anyway. On the other hand, if the user does catch the interruption subclass, they may have to clear the thread's interruption status in addition to catching the exception. This is in contrast to user code that catches InterruptedException; such code already has had the thread's interruption status cleared. I'm not sure if this will be an advantage or disadvantage though.

                  • 6. Re: Interruption and the Remoting 3 API
                    Trustin Lee Apprentice

                    Thanks for explanation David. If it's purely about interruption of a local thread, I'd prefer the option D without introducing a new subclass exceptions. I'm not sure it's cluttering but it will be very convenient for the API users though. Personally I chose interruptable one as default:

                    http://mina.apache.org/report/trunk/xref/org/apache/mina/common/IoFuture.html

                    As you pointed out, a user can know explicitly that the interruption status flag is set from the fact that he or she caught the InterruptedException by oneself. We will need more documentation if we deal it with any other exception classes (i.e. RemotingException subclasses).