groovy
  1. groovy
  2. GROOVY-5406

Exception in thread "Thread-2" groovy.lang.GroovyRuntimeException: exception while dumping process stream

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Not A Bug
    • Affects Version/s: 1.8.3
    • Fix Version/s: None
    • Component/s: groovy-jdk
    • Labels:
      None
    • Environment:
      JVM 1.6.0_14 on RHEL4u8
    • Number of attachments :
      0

      Description

      I received the following crash from a Groovy script sometimes:

      Exception in thread "Thread-2" groovy.lang.GroovyRuntimeException: exception while dumping process stream
          	at org.codehaus.groovy.runtime.ProcessGroovyMethods$ByteDumper.run(ProcessGroovyMethods.java:488)
          	at java.lang.Thread.run(Thread.java:619)
          Caused by: java.io.IOException: Bad file descriptor
          	at java.io.FileInputStream.available(Native Method)
          	at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
          	at java.io.FilterInputStream.read(FilterInputStream.java:90)
          	at org.codehaus.groovy.runtime.ProcessGroovyMethods$ByteDumper.run(ProcessGroovyMethods.java:484)
          	... 1 more
      

      I can't trap the exception from within the script and there's a few nested Groovy scripts but my guess is that it's from the call to Process.destroy(). Below is a snippet from my script which performs that call:

        def process =
          ["/tools/bin/reQrsh", "-q", "batch.q,compile.q", "-verbose", "-now", "n",
                                "-cwd", "-V", "-l", "os=redhat4$cbOpt,h_rt=28800",
                                "./$bobExe $bobArgs"].execute()
        def pipedOutputStream = new PipedOutputStream()
        process.consumeProcessOutput(
          new TeeOutputStream(System.out, pipedOutputStream),
          new TeeOutputStream(System.err, pipedOutputStream))
        new PipedInputStream(pipedOutputStream).eachLine \{
          (it =~ /<stripped>/).find \{ process.destroy() \}
        \}
          
        System.exit(0)
      

        Activity

        Hide
        Tim Yates added a comment -

        Which TeeOutputStream are you using? My guess would be that the condition is being met, so you are calling process.destroy() which is pulling the plug on one of the Streams. Also, does it still fail if you use an up to date version of Groovy and an up to date version of Java 6?

        Show
        Tim Yates added a comment - Which TeeOutputStream are you using? My guess would be that the condition is being met, so you are calling process.destroy() which is pulling the plug on one of the Streams. Also, does it still fail if you use an up to date version of Groovy and an up to date version of Java 6?
        Hide
        Uri Moszkowicz added a comment -

        From Apache commons library. It still fails with latest (2.0.0-beta-2 and 1.7.0_03). I guess it's really a JDK bug but one that's exposed with Groovy features. You can add an exception handler to the threads once they're created to ignore it. I can't think of an easy way to prevent it from being thrown - that is, to say that an already blocking read operation should unblock and the read loop should stop.

        Show
        Uri Moszkowicz added a comment - From Apache commons library. It still fails with latest (2.0.0-beta-2 and 1.7.0_03). I guess it's really a JDK bug but one that's exposed with Groovy features. You can add an exception handler to the threads once they're created to ignore it. I can't think of an easy way to prevent it from being thrown - that is, to say that an already blocking read operation should unblock and the read loop should stop.
        Hide
        Tim Yates added a comment - - edited

        This quick example seems to work:

        @Grab( 'commons-io:commons-io:2.2' )
        import org.apache.commons.io.output.TeeOutputStream as TOS
        
        def process = './test.sh'.execute()
        
        def pos = new PipedOutputStream()
        def pis = new PipedInputStream( pos )
        def tos = [ new TOS( System.out, pos ), new TOS( System.err, pos ) ]
        process.consumeProcessOutput( *tos )
        
        pis.eachLine {
          (it =~ /stop/).find {
            println "Stopping..."
            tos*.close()
            process.destroy()
          }
        }
        

        Can you try plugging in the process you are trying to run, and see if it works for you too?

        I think, rather than it being a bug, it's an issue with suddenly unplugging the process from the TeeOutputStream. Fingers crossed closing the streams nicely before calling process.destroy() will stop it happening... Without the tos*.close() line, I get the exception:

        Caught: java.io.IOException: Pipe broken
        java.io.IOException: Pipe broken
        

        On both OS X Snow Leopard and RedHat Enterprise Linux

        PS: My test.sh is:

        
        #!/bin/bash
        
        for i in {1..10}
        do
          if [ "$i" == "7" ]
          then
            echo "$i stop"
          else
            echo "$i continue"
          fi
          # Write something to the error stream
          echo "error stream" 1>&2
          sleep 1
        done
        
        Show
        Tim Yates added a comment - - edited This quick example seems to work: @Grab( 'commons-io:commons-io:2.2' ) import org.apache.commons.io.output.TeeOutputStream as TOS def process = './test.sh'.execute() def pos = new PipedOutputStream() def pis = new PipedInputStream( pos ) def tos = [ new TOS( System .out, pos ), new TOS( System .err, pos ) ] process.consumeProcessOutput( *tos ) pis.eachLine { (it =~ /stop/).find { println "Stopping..." tos*.close() process.destroy() } } Can you try plugging in the process you are trying to run, and see if it works for you too? I think, rather than it being a bug, it's an issue with suddenly unplugging the process from the TeeOutputStream . Fingers crossed closing the streams nicely before calling process.destroy() will stop it happening... Without the tos*.close() line, I get the exception: Caught: java.io.IOException: Pipe broken java.io.IOException: Pipe broken On both OS X Snow Leopard and RedHat Enterprise Linux PS: My test.sh is: #!/bin/bash for i in {1..10} do if [ "$i" == "7" ] then echo "$i stop" else echo "$i continue " fi # Write something to the error stream echo "error stream" 1>&2 sleep 1 done
        Hide
        Uri Moszkowicz added a comment -

        Yup that seems to have done it - thanks for the help!

        Show
        Uri Moszkowicz added a comment - Yup that seems to have done it - thanks for the help!
        Hide
        Tim Yates added a comment -

        Cool

        Glad I could help! You might as well delete the StackOverflow question too

        Good luck!

        Show
        Tim Yates added a comment - Cool Glad I could help! You might as well delete the StackOverflow question too Good luck!
        Hide
        Uri Moszkowicz added a comment -

        Even though all of the discussion is here, StackOverflow seems to get better rankings on Google. I will mark the question as answered though.

        Funny comic on topic: http://xkcd.com/979

        Show
        Uri Moszkowicz added a comment - Even though all of the discussion is here, StackOverflow seems to get better rankings on Google. I will mark the question as answered though. Funny comic on topic: http://xkcd.com/979

          People

          • Assignee:
            Unassigned
            Reporter:
            Uri Moszkowicz
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: