una - conectar ventanas en java eclipse
¿Cómo puedo hacer que un proceso hijo salga cuando lo hace el padre? (9)
Estoy iniciando un proceso secundario con ProcessBuilder, y necesito que el proceso hijo salga si el proceso padre lo hace. En circunstancias normales, mi código está deteniendo al niño correctamente. Sin embargo, si hago que el sistema operativo mate al padre, el niño continuará ejecutándose.
¿Hay alguna forma de "vincular" el proceso secundario con el padre, de manera que salga cuando maten al padre?
Preguntas similares:
Como ha descubierto, el sistema operativo le permite solucionar este problema. En su lugar, cree un recurso compartido por ambos procesos. Cuando el padre aborta el recurso, el niño reacciona cerrándose. Por ejemplo:
Cree un subproceso con un socket TCP / IP del lado del servidor en el modo de aceptación en el principal en un puerto de alto número aleatorio. Cuando el niño comienza, pase el número de puerto como parámetro (variable de entorno, entrada en la base de datos, lo que sea). Haga que cree un hilo y abra ese zócalo. Tienen el hilo sentado en el zócalo para siempre. Si la conexión se cae alguna vez, haga que el niño salga.
o
Cree un hilo en el padre que actualiza continuamente la fecha de actualización en un archivo. (La frecuencia con la que depende la cantidad de granularidad entre el cierre y el apagado que necesita). El niño tiene un hilo que supervisa el tiempo de actualización del mismo archivo. Si no se actualiza después de un intervalo específico, cierre automáticamente.
Como probé, si el padre es asesinado, entonces el ppid de un niño se convertirá en 1. Entonces, probablemente podamos matar cualquier proceso que tenga ppid = 1.
Intente enviar una señal de muerte al proceso secundario desde el padre cuando el padre se detiene
No existe un vínculo entre un proceso hijo y su padre. Pueden conocer el ID de proceso del otro, pero no hay una conexión dura entre ellos. De lo que estás hablando es de un proceso huérfano . Y es una preocupación de nivel de sistema operativo. Es decir, cualquier solución depende probablemente de la plataforma.
Casi lo único que se me ocurre es pedirle al niño que verifique el estado de sus padres periódicamente, saliendo si el padre se apaga. Sin embargo, no creo que esto sea tan confiable.
Para Windows, se me ocurrió este truco de votación:
static int getPpid(int pid) throws IOException {
Process p = Runtime.getRuntime().exec("C://Windows//System32//wbem//WMIC.exe process where (processid="+pid+") get parentprocessid");
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
br.readLine();
br.readLine();
String ppid= br.readLine().replaceAll(" ","");
return Integer.parseInt(ppid);
}
static boolean shouldExit() {
try {
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
int ppid = getPpid(Integer.parseInt(pid));
/* pppid */ getPpid(ppid);
} catch (Exception e) {
return true;
}
return false;
}
Para los procesos de un solo niño, puede gestionar esto invirtiendo la relación padre / hijo. Vea mi respuesta a una posterior encarnación de esta pregunta.
Proporcione a los hackers una forma similar a la respuesta de @tomkri y también proporcione el código de demostración.
Si el proceso de su hijo no necesita el uso de la secuencia de entrada, simplemente redirija la secuencia de entrada del proceso secundario a la secuencia de entrada del proceso principal. A continuación, agregue un subproceso en el elemento secundario para leer siempre la secuencia de entrada y, cuando este subproceso no pueda leer nada de la secuencia de entrada, este proceso secundario finaliza. Entonces el proceso padre sale -> la corriente de entrada de los padres no existe -> la corriente de entrada del niño no existe -> el proceso hijo sale.
Aquí está el código de la demo, todo en Java.
Proceso principal:
package process.parent_child;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
public class ParentProc {
public static void main(String[] args) {
System.out.println("I''m parent.");
String javaHome = System.getProperty("java.home");
String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
ProcessBuilder builder = new ProcessBuilder(javaBin, "process.parent_child.ChildProc");
// Redirect subprocess''s input stream to this parent process''s input stream.
builder.redirectInput(Redirect.INHERIT);
// This is just for see the output of child process much more easily.
builder.redirectOutput(Redirect.INHERIT);
try {
Process process = builder.start();
Thread.sleep(5000);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Parent exits.");
}
}
Proceso del niño:
package process.parent_child;
import java.io.IOException;
import java.util.Scanner;
public class ChildProc {
private static class StdinListenerThread extends Thread {
public void run() {
int c;
try {
c = System.in.read();
while ( c != -1 ) {
System.out.print(c);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("/nChild exits.");
System.exit(0);
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println("I''m child process.");
StdinListenerThread thread = new StdinListenerThread();
thread.start();
Thread.sleep(10000);
}
}
Después de ejecutar este proceso principal con el siguiente comando:
java process.parent_child.ParentProc
Ya verás
I''m parent.
I''m child process.
Parent exits.
xmpy-mbp:bin zhaoxm$
Child exits
El proceso secundario sale inmediatamente cuando sale el proceso principal.
Si bien no puede protegerse contra un aborto fuerte (por ejemplo, SIGKILL en Unix), puede protegerse contra otras señales que hacen que su proceso principal se apague (por ejemplo, SIGINT) y limpiar su proceso secundario. Puede lograr esto a través del uso de los ganchos de cierre: vea Runtime#addShutdownHook , así como una pregunta SO relacionada here .
Tu código podría verse más o menos así:
String[] command;
final Process childProcess = new ProcessBuilder(command).start();
Thread closeChildThread = new Thread() {
public void run() {
childProcess.destroy();
}
};
Runtime.getRuntime().addShutdownHook(closeChildThread);
Simplemente puede comenzar una lectura de hilo desde System.in en el proceso secundario. Si no está escribiendo para stdin de su hijo, nadie más lo hará y el hilo bloqueará "para siempre". Pero obtendrá un EOF (o una excepción), si el proceso principal se mata o muere de lo contrario. Entonces puedes apagar al niño también. (El proceso secundario comenzó con java.lang.ProcessBuilder)