Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8268939

ProcessBuilder.waitFor() immediately returns with exit code = 1

    XMLWordPrintable

    Details

    • Subcomponent:
    • Introduced In Build:
      b01
    • Introduced In Version:
      16
    • CPU:
      x86_64
    • OS:
      windows_10

      Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 amd64
      OpenJDK 16.0.1


      A DESCRIPTION OF THE PROBLEM :
      In a complex desktop application I'm calling out to some native executables to perform certain operations (ffmpeg, ffprobe) using the ProcessBuilder class with the following code. This code works great in OpenJDK 11.0.3, but fails in some scenarios, but always in those scenarios, in OpenJDK 16.0.1.

      Commands that are being run (all work in OpenJDK 11.0.3) and their run status in OpenJDK 16.0.1:
      WORKS C:\{full-path}\ffmpeg.exe -i C:\{full-path}\1420796.mp4 -af "volumedetect" -vn -sn -dn -f
      FAILS C:\{full-path}\ffmpeg.exe -v fatal -i C:\{full-path}\1420796.mp4 -y -ignore_unknown C:\{full-path}\media\f9c503917f56490f8167b2f74ff7197b.mp4
      NOT REACHED C:\{full-path}\ffprobe.exe -v quiet -print_format json -show_format -show_streams C:\{full-path}\media\f9c503917f56490f8167b2f74ff7197b.mp4
      NOT REACHED C:\{full-path}\ffmpeg.exe -v fatal -i C:\{full-path}\1420796.mp4 -vf fps=2 -frames:v 10 -vsync vfr C:\{full-path}\c03adad5eb924c8bad61fde963529873\frame%02d.jpg

      The first command appears to work all the time. The second command is where it fails and it appears to fail all the time. The last two commands are not reached because the second command fails. In OpenJDK 11.0.3, the second command takes longer to complete than the other commands. The second command fails immediately in OpenJDK 16.0.1 and there is no output from ProcessBuilder/Process to review - I only get back an exit code of 1. If I paste these commands as is into a terminal, they execute successfully.

      REGRESSION : Last worked in version 11

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Code sample that's failing

      // command is a List<string>
      ProcessBuilder pb = new ProcessBuilder(command);
      pb.redirectErrorStream(true);
      Process process = null;

      try {
          process = pb.start();

          BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
          String line = null;
          StringBuilder s = new StringBuilder();
          while((line = input.readLine()) != null) {
              s.append(line).append(Constants.NEW_LINE);
          }
          
          int exitCode = process.waitFor();
          
          try {
              input.close();
          } catch (IOException e) {
              // I ignore this, but it never gets here
          }
          
          if (exitCode != 0) {
              String message = s.toString();
              throw new Exception(message);
          }
          
          return s.toString();
      } finally {
          if (process != null) {
              process.destroy();
          }
      }

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The expected result is what I'm seeing OpenJDK 11.0.3 where the command is executed successfully and thread blocks until the command is completed.
      ACTUAL -
      The command appears to fail immediately with an exit code of 1 with no other output of any kind.

      ---------- BEGIN SOURCE ----------
      See the source provided in the steps to reproduce section
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      For now, I'm linking to the Apache Commons Exec library that hasn't seen an update in 7 years and doesn't support the Java 9 module system.

      Using the Apache Commons Exec package the same commands listed DO work in both 11 and 16:

      // command is a List<string>
      CommandLine cmdLine = CommandLine.parse(String.join(" ", command));

      try {
          ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
          PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
          DefaultExecutor exec = new DefaultExecutor();
          exec.setExitValue(0);
          exec.setStreamHandler(streamHandler);
          int exitCode = exec.execute(cmdLine);
          return outputStream.toString();
      } catch (Exception ex) {
          throw ex;
      }

      FREQUENCY : always


        Attachments

          Activity

            People

            Assignee:
            rriggs Roger Riggs
            Reporter:
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated: