Existe algum risco de uma condição de corrida ao executar ps?

5

Estou iniciando um processo de longa duração (em Java, na chance relevante) e gostaria de capturar seu PID via ps . Eu estou essencialmente fazendo isso:

Process longRunningProcess = new ProcessBuilder(...).start();

Process psProcess = new ProcessBuilder("ps").start();
psProcess.waitFor();
// extract the PID from the output of psProcess

Ou efetivamente de forma equivalente no Bash:

$ long_running_process > /dev/null & ps

A questão é, é possível que o processo de longa duração esteja em algum estado ainda em fase de inicialização que ps ainda não irá relatar? Ou existe algum tipo de garantia de que, no momento em que ps for executado, o processo de longa duração será iniciado o suficiente para ficar visível? Executando o comando repetidamente aparece para sempre incluir o processo, mas isso obviamente não é prova de nada.

Este artigo alerta que pode haver uma condição de corrida nos comandos iniciados < em> after ps é iniciado (por exemplo, ps | grep ), mas não menciona nada sobre processos iniciados antes de ps .

    
por dimo414 30.06.2015 / 01:18

3 respostas

0

Se as operações forem comparáveis ao OpenJDK v6-b14 , o PID será esteja disponível para ps ao verificar o sistema de arquivos /proc virtual. Você não pode ter certeza de que o processo realmente começou (ou seja, fez qualquer coisa); tudo que você sabe é que um PID foi reservado e agendado (pense nisso, o processo pode ter morrido e estar em um estado zumbi).

No entanto, como ps bloqueia você em sistemas Unix, você pode usar o Reflection para acessar o objeto retornado pelo ProcessBuilder, com o entendimento de que ele o levará a um UnixProcess:

final class  [More ...] UNIXProcess extends Process {
    private FileDescriptor stdin_fd;
    private FileDescriptor stdout_fd;
    private FileDescriptor stderr_fd;
    private int pid; <----------------------------------------------
    private int exitcode;

É claro que este é um hack, mas não muito diferente do ps - e certamente mais rápido. E não é realmente tão arriscado - eu não vejo um campo pid chamado pid mudando muito em breve.

    
por 30.06.2015 / 01:43
0

Eu não estou intimamente familiarizado com o Java, mas no momento em que ProcessBuilder.start retorna, ele deve ter começado alguma coisa. Ele pode ter configurado um callback dentro do thread existente para ser executado posteriormente para criar o processo filho, ou pode ter iniciado outro thread no mesmo processo que eventualmente cria o processo filho, ou pode ter chamado fork para criar um processo filho. Duvido que seja um dos dois primeiros, já que seria mais difícil acertar; qualquer referência ao subprocesso, incluindo mecanismos para se comunicar com ele ou para recuperar seu status, teria que esperar até que o processo seja criado.

Assim, quando ProcessBuilder.start retornar, você pode ter certeza de que o processo foi criado. No entanto, isso não significa que não haja condições de corrida. Se o processo sair ou travar logo após ter sido iniciado, ele pode estar morto quando você olhar para ele. O ID do processo ainda existirá até que seu pai chame uma das wait família de chamadas do sistema ; se o processo tiver morrido, o PID permanece válido desde que o processo seja um zumbi , ou seja, contanto que o pai tenha chamado wait .

Portanto, a única maneira de ter certeza de que o ID do processo é válido é coordenar com o pai e garantir que o pai já tenha chamado fork e ainda não tenha chamado wait .

    
por 30.06.2015 / 01:42
0

Eu enfrentei esse problema no passado. Eu resolvi isso fazendo:

exec java WhateverTheClassNameIs -p $$

onde "-p" é um sinalizador que indica "meu PID é o valor desse sinalizador". Você tem que codificar essa parte em seu método Java main() .

Essa deve ser a última linha do script shell, já que o exec primitivo carrega java sobre o próprio shell. O status de saída do seu programa será o status de saída de WhateverTheClassNameIs , não o status de saída do shell, pois ele realmente não existe mais. Isso pode levar a um código um pouco contorcido, mas não consegui encontrar uma maneira melhor de obter o PID em um programa Java.

    
por 30.06.2015 / 02:55