Skip to content

Commit

Permalink
Fixing race in exit code after a process has already completed
Browse files Browse the repository at this point in the history
  • Loading branch information
DavyLandman committed Sep 11, 2024
1 parent 8c298e0 commit 1ce9e59
Showing 1 changed file with 19 additions and 13 deletions.
32 changes: 19 additions & 13 deletions src/org/rascalmpl/library/util/ShellExec.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.rascalmpl.exceptions.RuntimeExceptionFactory;
import org.rascalmpl.uri.URIResolverRegistry;
Expand All @@ -34,7 +35,8 @@
import io.usethesource.vallang.IValueFactory;

public class ShellExec {
private static Map<IInteger, Process> runningProcesses = new HashMap<>();
private static Map<IInteger, Process> runningProcesses = new ConcurrentHashMap<>();
private static Map<IInteger, IInteger> processExitCodes = new ConcurrentHashMap<>();
private static Map<IInteger, InputStreamReader> processInputStreams = new HashMap<>();
private static Map<IInteger, BufferedReader> processErrorStreams = new HashMap<>();
private static Map<IInteger, OutputStreamWriter> processOutputStreams = new HashMap<>();
Expand Down Expand Up @@ -107,16 +109,18 @@ public IInteger exitCode(IInteger pid) {
Process p = runningProcesses.get(pid);

if (p == null) {
throw RuntimeExceptionFactory.illegalArgument(pid, "unknown process");
IInteger storedExitCode = processExitCodes.get(pid);
if (storedExitCode == null) {
throw RuntimeExceptionFactory.illegalArgument(pid, "unknown process");
}
return storedExitCode;
}

while (true) {
try {
return vf.integer(p.waitFor());
}
catch (InterruptedException e) {
continue;
}
try {
return vf.integer(p.waitFor());
}
catch (InterruptedException e) {
throw RuntimeExceptionFactory.javaException(e, null, null);
}
}

Expand Down Expand Up @@ -228,12 +232,13 @@ public synchronized void killProcess(IInteger processId, IBool force) {
runningProcess.destroy();
}
}
new Thread("zombie process clean up") {

Thread waitForCleared = new Thread("zombie process clean up") {
public void run() {
while (true) {
try {
runningProcess.waitFor();
processExitCodes.put(processId, vf.integer(runningProcess.exitValue()));
runningProcesses.remove(processId);
return;
}
Expand All @@ -244,8 +249,9 @@ public void run() {
}
}
};
}.start();

};
waitForCleared.setDaemon(true);
waitForCleared.start();

return;
}
Expand Down

0 comments on commit 1ce9e59

Please sign in to comment.