Состояние гонки между временем Runtime.exec запускает новую тему, чтобы начать процесс, и когда вы сообщите об этом процессе, чтобы уничтожить себя.
Я нахожусь на машине linux, поэтому я буду использовать файл UNIXProcess.class для иллюстрации.
Runtime.exec(...)
создаст новый ProcessBuilder
и запустит его, который на машине unix создает новый экземпляр UNIXProcess
. В конструкторе UNIXProcess
есть этот блок кода, который фактически выполняет процесс в качестве фона (раздвоенный) резьбы:
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread t = new Thread("process reaper") {
public void run() {
try {
pid = forkAndExec(prog,
argBlock, argc,
envBlock, envc,
dir,
redirectErrorStream,
stdin_fd, stdout_fd, stderr_fd);
} catch (IOException e) {
gate.setException(e); /*remember to rethrow later*/
gate.exit();
return;
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
stdin_stream = new BufferedOutputStream(new
FileOutputStream(stdin_fd));
stdout_stream = new BufferedInputStream(new
FileInputStream(stdout_fd));
stderr_stream = new FileInputStream(stderr_fd);
return null;
}
});
gate.exit(); /* exit from constructor */
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null;
}
});
Обратите внимание, что фоновый поток устанавливает поле pid
который является идентификатором процесса UNIX. Это будет использоваться destroy()
, чтобы сообщить операционной системе, которая должна убить.
Потому что нет способа убедиться, что этот фоновый поток запущен при вызове destroy()
, мы можем попытаться убить процесс до его запуска ИЛИ мы можем попытаться убить процесс до того, как будет задано поле pid; ПИД- неинициализированный и поэтому 0. Таким образом, я думаю, призывая уничтожить слишком рано делать эквивалент kill -9 0
Существует даже комментарий в UNIXProcess destroy()
, что намекает на это, но только считает вызов уничтожить после того, как процесс уже закончил , а не до его начала:
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
ИДП поле даже не помеченных как летучий поэтому мы можем не увидеть даже самое последнее значение все время.
Вы получаете исключение? – SLaks
Не исключение. – Bastien
Откуда вы знаете? – SLaks