Can $! causar condições de corrida quando usado em scripts em paralelo?

8

Digamos que eu tenha vários scripts de bash executados em paralelo, com código como o seguinte:

#!/bin/bash

tail -f /dev/null &
echo "pid is "$!

É $!garantido que eu me forneça o PID da tarefa em segundo plano mais recente desse script ou é a tarefa em segundo plano mais recente globalmente? Só estou curioso para saber se contar com esse recurso pode causar condições de corrida quando o PID retornado for de um processo iniciado em outro script.

philraj
fonte

Respostas:

16

$!é garantido para fornecer o pid do processo em que o shell executou esse tailcomando. Os shells são de thread único, cada shell vive em seu próprio processo com seu próprio conjunto de variáveis. Não há como o $!shell de um shell vazar para outro shell, assim como atribuir uma variável de shell em um shell não afetará a variável de mesmo nome em outro shell (se deixarmos de lado as variáveis ​​universais do fishshell) .

Agora, tail -f /dev/nullé um comando que é executado indefinidamente, mas para comandos de curta duração, observe que, como existe um número limitado de possíveis identificações de processo, elas inevitavelmente acabam sendo reutilizadas.

No:

true &
pid=$!

Isso $pidconterá o ID do processo em que o shell foi executado true, mas quando você o usar $pid, esse pid poderá estar morto e pode estar se referindo a um processo diferente.

Stéphane Chazelas
fonte
3
Sim, eu estava ciente do seu segundo ponto e, se você quiser criar um gerenciador de processos em segundo plano confiável, precisará usar uma linguagem que garanta que você saberá o momento exato em que um processo filho terminou e seu PID foi devolvido ao pool , que aparentemente shell scripts não podem, uma vez que colhem processos filho de forma agressiva. Obrigado pela explicação clara.
philraj
5
@philraj, no zsh, você pode instalar manipuladores no SIGCHLD, que são processados ​​após o término de tarefas assíncronas e usados $jobstate/$jobtextpara inspecionar o status do processo. Não sem corrida, já que a criança já é colhida no momento em que a armadilha é executada, mas isso significa janelas de corrida muito curtas, onde é muito improvável que os pids já sejam reutilizados.
Stéphane Chazelas