package org.jruby.util.io;
import jnr.constants.platform.Errno;
import jnr.constants.platform.Signal;
import org.jruby.Ruby;
import java.io.InputStream;
import java.io.OutputStream;
public class POSIXProcess extends Process {
private final Ruby runtime;
private final long finalPid;
volatile Integer exitValue;
volatile Integer status;
public POSIXProcess(Ruby runtime, long finalPid) {
this.runtime = runtime;
this.finalPid = finalPid;
exitValue = null;
}
@Override
public OutputStream getOutputStream() {
return null;
}
@Override
public InputStream getInputStream() {
return null;
}
@Override
public InputStream getErrorStream() {
return null;
}
@Override
public synchronized int waitFor() throws InterruptedException {
if (exitValue == null) {
int[] stat_loc = {0};
retry: while (true) {
stat_loc[0] = 0;
int result = runtime.getPosix().waitpid((int)finalPid, stat_loc, 0);
if (result == -1) {
Errno errno = Errno.valueOf(runtime.getPosix().errno());
switch (errno) {
case EINTR:
runtime.getCurrentContext().pollThreadEvents();
continue retry;
case ECHILD:
return -1;
default:
throw new RuntimeException("unexpected waitpid errno: " + Errno.valueOf(runtime.getPosix().errno()));
}
}
break;
}
status = stat_loc[0];
if (PosixShim.WAIT_MACROS.WIFEXITED((long)status)) {
exitValue = PosixShim.WAIT_MACROS.WEXITSTATUS((long)status);
} else if (PosixShim.WAIT_MACROS.WIFSIGNALED((long)status)) {
exitValue = PosixShim.WAIT_MACROS.WTERMSIG((long)status);
} else if (PosixShim.WAIT_MACROS.WIFSTOPPED((long)status)) {
exitValue = PosixShim.WAIT_MACROS.WSTOPSIG((long)status);
}
}
return exitValue;
}
@Override
public int exitValue() {
try {
return waitFor();
} catch (InterruptedException ie) {
throw new IllegalThreadStateException();
}
}
@Override
public void destroy() {
runtime.getPosix().kill((int)finalPid, Signal.SIGTERM.intValue());
}
public int status() {
try {
waitFor();
} catch (InterruptedException ie) {
throw new IllegalThreadStateException();
}
return status == null ? -1 : status;
}
}