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

Launching ksh (shell) from within Java through ProcessBuilder causes ksh process to crash with EXC_BAD_ACCESS (SIGSEGV)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P2 P2
    • 20
    • 20
    • hotspot

      Consider the trivial program below which uses the ProcessBuiler API to launch the "/bin/ksh" binary. The command it uses to launch is /bin/ksh --version and is expected to write out the version of ksh. However, running that Java program which launches ksh causes ksh to crash with EXC_BAD_ACCESS (SIGSEGV).

      This issue has been observed on macosx system and happens only on Java 20 and JDK mainline. The same program works fine on Java 19 and previous versions.

      The reproducing code follows (the same is attached to this JBS issue):

      ------
      import java.io.*;
      import java.nio.file.Path;
      import java.util.*;

      public class Test {
      public static void main(final String[] args) throws Exception {
      System.out.println("Using Java version " + System.getProperty("java.specification.version"));
      final String[] cmd = new String[] {"/bin/ksh", "--version"};
      final ProcessBuilder pb = new ProcessBuilder(cmd);
              System.out.println("Running command: " + Arrays.toString(cmd));
              final Process p = pb.start();
              final String s = waitAndCapture(p);
              System.out.println("Process id: " + p.pid() + " Exit code " + p.exitValue());
              System.out.println("Command result: ");
              System.out.println(s);
      }


      private static String waitAndCapture(Process p) throws IOException, InterruptedException {
              ByteArrayOutputStream bout = new ByteArrayOutputStream();
              InputStream in = null;
              InputStream err = null;
              OutputStream out = null;
              try {
                  int c;
                  in = p.getInputStream();
                  while ((c = in.read()) != -1) {
                      bout.write(c);
                  }
                  err = p.getErrorStream();
                  while ((c = err.read()) != -1) {
                      bout.write(c);
                  }
                  out = p.getOutputStream();
                  p.waitFor();
              } finally {
                  close(in, out, err);
              }

              return bout.toString();
          }

          private static void close(final Closeable... closeables) {
              for (Closeable c : closeables) {
                  if (c != null) {
                      try {
                          c.close();
                      } catch (Exception e) {
                          // Ignore
                      }
                  }
              }
          }
      }
      ------
      Running the following command:

      java Test.java

      results in:

      Using Java version 21
      Running command: [/bin/ksh, --version]
      Process id: 58578 Exit code 139
      Command result:

      That exit code 139 for ksh implies the SIGSEGV crash. The crash logs will be available on system specific location and I collected it from my local setup. Here's the relevant parts including stack backtrace which shows the exception happens within ksh binary:

      Process: ksh [58536]
      Path: /bin/ksh
      Identifier: ksh
      Version: ???
      Code Type: ARM-64 (Native)
      Parent Process: java [58534]
      Responsible: Terminal [636]
      User ID: xxx

      Date/Time: 2022-12-22 13:40:16.0739 +0530
      OS Version: macOS 13.0.1 (22A400)
      Report Version: 12
      ...

      Crashed Thread: 0 Dispatch queue: com.apple.main-thread

      Exception Type: EXC_BAD_ACCESS (SIGSEGV)
      Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
      Exception Codes: 0x0000000000000001, 0x0000000000000000

      Termination Reason: Namespace SIGNAL, Code 11 Segmentation fault: 11
      Terminating Process: exc handler [58536]

      ...

      Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
      0 ksh 0x104321dac sh_ioinit + 76
      1 ksh 0x104321d94 sh_ioinit + 52
      2 ksh 0x10431e898 sh_init + 524
      3 ksh 0x104308798 sh_main + 72
      4 dyld 0x191aebe50 start + 2544


      Thread 0 crashed with ARM Thread State (64-bit):
          x0: 0x0000000000000000 x1: 0x0000000000000000 x2: 0x000000000000000b x3: 0x0000000000000000
          x4: 0x0000000000000000 x5: 0x0000600002a10474 x6: 0x000000000000000a x7: 0x0000000000000001
          x8: 0x00000001043fb680 x9: 0x0000000000000000 x10: 0x0000600001d10000 x11: 0x00000000000000c0
         x12: 0x0000000000000055 x13: 0x00000000000007fb x14: 0x000000008002a7fb x15: 0x000000008002a7fb
         x16: 0x0000000191dd77cc x17: 0x00000001f2328c98 x18: 0x0000000000000000 x19: 0x00000001043fb878
         x20: 0x00000001043f8da0 x21: 0x000000016bb07480 x22: 0x0000000104401de8 x23: 0x0000000000000002
         x24: 0x00000001ed9e83c0 x25: 0x0000000000000000 x26: 0x0000000000000000 x27: 0x0000000000000000
         x28: 0x0000000000000000 fp: 0x000000016bb06b40 lr: 0x0000000104321d94
          sp: 0x000000016bb06b20 pc: 0x0000000104321dac cpsr: 0x20001000
         far: 0x0000000000000000 esr: 0x92000046 (Data Abort) byte write Translation fault

      Running the same program against Java 19 returns the expected result:

      $> <path-to-jdk-19>/bin/java Test.java
      results in:

      Using Java version 19
      Running command: [/bin/ksh, --version]
      Process id: 58682 Exit code 2
      Command result:
        version sh (AT&T Research) 93u+ 2012-08-01

            gziemski Gerard Ziemski
            jpai Jaikiran Pai
            Votes:
            0 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated:
              Resolved: