JRuby (please use github issues at http://bugs.jruby.org)
  1. JRuby (please use github issues at http://bugs.jruby.org)
  2. JRUBY-4135

Can't interrupt busy Ruby instance from Java - InterruptException ignored.

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: JRuby 1.3
    • Fix Version/s: None
    • Component/s: Java Integration
    • Labels:
      None
    • Environment:
      all
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      public void testInturruptingRubyInstance() throws Exception
      {
      Thread thread = new Thread(){
      public void run()

      { JavaEmbedUtils.initialize(Collections.EMPTY_LIST).runFromMain(new ByteArrayInputStream("sleep(5)".getBytes()), "Sleeper"); }

      };
      thread.start();
      long before = System.currentTimeMillis();
      thread.interrupt();
      thread.join();
      long millis = System.currentTimeMillis() - before;
      assertEquals(("ruby ignored interrupt for " + millis + " millis."), true, millis < 2000);
      }

        Activity

        Hide
        Micah Martin added a comment -

        [11:50am] MenTaLguY: either you propagate the exception, or else you remember the interrupt state and re-interrupt the thread after you wake up
        [11:51am] enebo: MenTaLguY: Well that is something which seems reasonable but it does not match Ruby semantics in this case right?
        [11:55am] enebo: micahmartin: It seems we should have a way from Java to deliver a user-supplied interrupt to a Ruby thread and have it not get eaten
        [11:55am] micahmartin: I'd agree... shall I submit a ticket?
        [11:55am] enebo: It is unfortunate that sleep and interrupt/wait all use the same exception
        [11:56am] enebo: micahmartin: yeah for sure....I am not sure how we will attack this, but we need to keep track of it
        [11:56am] enebo: wait=notify in above sentence

        Show
        Micah Martin added a comment - [11:50am] MenTaLguY: either you propagate the exception, or else you remember the interrupt state and re-interrupt the thread after you wake up [11:51am] enebo: MenTaLguY: Well that is something which seems reasonable but it does not match Ruby semantics in this case right? [11:55am] enebo: micahmartin: It seems we should have a way from Java to deliver a user-supplied interrupt to a Ruby thread and have it not get eaten [11:55am] micahmartin: I'd agree... shall I submit a ticket? [11:55am] enebo: It is unfortunate that sleep and interrupt/wait all use the same exception [11:56am] enebo: micahmartin: yeah for sure....I am not sure how we will attack this, but we need to keep track of it [11:56am] enebo: wait=notify in above sentence
        Hide
        Charles Oliver Nutter added a comment -

        So is the problem here that because we really want to try to sleep for the full period, we ignore the interrupt? I'm not sure how we can work around that. I tried having it check for thread.isInterrupted and bailing out, but that didn't seem to fix it.

        Show
        Charles Oliver Nutter added a comment - So is the problem here that because we really want to try to sleep for the full period, we ignore the interrupt? I'm not sure how we can work around that. I tried having it check for thread.isInterrupted and bailing out, but that didn't seem to fix it.
        Hide
        Micah Martin added a comment -

        In my case, I'm executing ruby code that could have been written by
        anyone. In normal cases the thread that spawns the Ruby instance
        should terminate normally within a reasonable amount of time. But
        since I don't know what that code is doing, I'd like to be able to
        timeout and force a ruby instance to stop executing. It seems to me
        that thread.interrupt() should do the trick.

        Show
        Micah Martin added a comment - In my case, I'm executing ruby code that could have been written by anyone. In normal cases the thread that spawns the Ruby instance should terminate normally within a reasonable amount of time. But since I don't know what that code is doing, I'd like to be able to timeout and force a ruby instance to stop executing. It seems to me that thread.interrupt() should do the trick.
        Hide
        Charles Oliver Nutter added a comment -

        Generally speaking, normal Java thread interrupt is not enough because we implement Ruby thread semantics on top of Java's thread operations. But I certainly don't want to recommend the Ruby way, which is to #kill or #raise on the Ruby Thread object.

        Perhaps you can have a look at RubyThread.sleep and RubyKernel.sleep to see if altering how they do the sleep can be altered to allow a simple Java thread.interrupt to wake them? That's about the best we can do, since thread.interrupt doesn't always wake a thread from arbitrary blocking calls.

        Show
        Charles Oliver Nutter added a comment - Generally speaking, normal Java thread interrupt is not enough because we implement Ruby thread semantics on top of Java's thread operations. But I certainly don't want to recommend the Ruby way, which is to #kill or #raise on the Ruby Thread object. Perhaps you can have a look at RubyThread.sleep and RubyKernel.sleep to see if altering how they do the sleep can be altered to allow a simple Java thread.interrupt to wake them? That's about the best we can do, since thread.interrupt doesn't always wake a thread from arbitrary blocking calls.
        Hide
        Thomas E Enebo added a comment -

        But if the caller is coming from Java and we have a ThreadContext.interrupt method we could then flag that a Java-requested interrupt is being requested. We can add logic into our Ruby interrupt logic to honor breaking out of Ruby sleep impl based on this since we know at least one Java non-spurious wakeup is requested.

        So this usecase gives better control to Java embedder and acts closer to Java semantics while not changing the Ruby semantics.

        Show
        Thomas E Enebo added a comment - But if the caller is coming from Java and we have a ThreadContext.interrupt method we could then flag that a Java-requested interrupt is being requested. We can add logic into our Ruby interrupt logic to honor breaking out of Ruby sleep impl based on this since we know at least one Java non-spurious wakeup is requested. So this usecase gives better control to Java embedder and acts closer to Java semantics while not changing the Ruby semantics.

          People

          • Assignee:
            Unassigned
            Reporter:
            Micah Martin
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: