Can $! causar condiciones de carrera cuando se usa en scripts que se ejecutan en paralelo?

8

Digamos que tengo varios scripts de bash que se ejecutan en paralelo, con un código como el siguiente:

#!/bin/bash

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

¿Se $!garantiza que me dará el PID de la tarea en segundo plano más reciente en ese script , o es la tarea en segundo plano más reciente a nivel mundial? Tengo curiosidad por saber si confiar en esta característica puede causar condiciones de carrera cuando el PID que devuelve proviene de un proceso iniciado en otro script.

philraj
fuente

Respuestas:

16

$!está garantizado para darle el pid del proceso en el que el shell ejecutó ese tailcomando. Los shells son de un solo subproceso, cada shell vive en su propio proceso con su propio conjunto de variables. No hay forma $!de que un shell se filtre en otro shell, al igual que asignar una variable de shell en un shell no va a afectar la variable del mismo nombre en otro shell (si dejamos de lado las variables universales del fishshell) .

Ahora, tail -f /dev/nulles un comando que se ejecuta indefinidamente, pero para los comandos de corta duración, tenga en cuenta que, dado que hay un número limitado de posibles identificadores de proceso, los identificadores de proceso inevitablemente terminan siendo reutilizados.

En:

true &
pid=$!

Eso $pidcontendrá la identificación del proceso donde se ejecutó el shell true, pero para el momento en que lo use $pid, ese pid podría estar muerto y podría estar refiriéndose a un proceso diferente.

Stéphane Chazelas
fuente
3
Sí, estaba al tanto de su segundo punto, y que si desea crear un administrador de procesos en segundo plano confiable, debe usar un lenguaje que le garantice que sabrá el momento exacto en que un proceso secundario ha salido y su PID ha sido devuelto al grupo , que aparentemente los scripts de shell no pueden, ya que cosechan procesos secundarios agresivamente. Gracias por la explicación clara.
philraj
55
@philraj, en zsh, puede instalar controladores en SIGCHLD que se procesan al finalizar los trabajos asincrónicos y se utilizan $jobstate/$jobtextpara inspeccionar el estado del proceso allí. No sin raza, ya que el niño ya está cosechado en el momento en que se ejecuta la trampa, pero eso significa ventanas de carrera muy cortas donde es muy poco probable que los pids ya se reutilicen.
Stéphane Chazelas