Skip to content

I processi in background ottengono un SIGHUP quando si disconnettono?

Indaghiamo su tutto Internet e quindi ti diamo la soluzione al tuo dubbio, in caso di dubbio puoi lasciare il dubbio e noi risponderemo perché siamo qui per servirti.

Soluzione:

Soluzione 1:

Risposta trovata.

Per BASH, questo dipende dal file huponexit opzione shell, che può essere visualizzata e/o impostata utilizzando l'opzione built-in shopt comando.

Sembra che questa opzione sia disattivata per impostazione predefinita, almeno sui sistemi basati su RedHat.

Maggiori informazioni sulla pagina man di BASH:

La shell esce per impostazione predefinita alla ricezione di un SIGHUP. Prima di uscire, una shell interattiva invia nuovamente il SIGHUP a tutti i lavori, in esecuzione o interrotti. I lavori interrotti vengono inviati SIGCONT per garantire che ricevano il SIGHUP. Per impedire alla shell di inviare il segnale a un particolare lavoro, dovrebbe essere rimosso dalla tabella dei lavori con l'integrato disown (vedere COMANDI INCORPORATI DELLA SHELL sotto) o contrassegnato per non ricevere SIGHUP usando disown -h.

Se l'opzione della shell huponexit è stata impostata con shopt, bash invia un SIGHUP a tutti i job quando esce una shell di login interattiva.

Soluzione 2:

Verrà inviato SIGHUP nei miei test:

Shell1:

[[email protected]: ~] ssh localhost
[[email protected]: ~] perl -e sleep & 
[1] 1121
[[email protected]: ~] ps
  PID TTY          TIME CMD
 1034 pts/46   00:00:00 zsh
 1121 pts/46   00:00:00 perl
 1123 pts/46   00:00:00 ps

Guscio2:

strace -e trace=signal -p1121

Shell1 Ancora:

[[email protected]: ~] exit
zsh: you have running jobs.
[[email protected]: ~] exit
zsh: warning: 1 jobs SIGHUPed
Connection to localhost closed.

Di nuovo Shell2:

strace -e trace=signal -p1121
Process 1121 attached - interrupt to quit
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGHUP (Hangup) @ 0 (0) ---
Process 1121 detached

Perché funziona ancora?:

La programmazione avanzata nell'ambiente Unix di Stevens copre questo argomento nella sezione 9.10: Gruppi di processi orfani. La sezione più rilevante è:

Poiché il gruppo di processi è orfano quando il genitore termina, POSIX.1 richiede che a ogni processo nel gruppo di processi appena orfano che viene arrestato (come lo è il nostro figlio) venga inviato il segnale di riaggancio (SIGHUP) seguito dal segnale di continuazione (SIGCONT ).

Ciò fa sì che il bambino continui, dopo aver elaborato il segnale di riaggancio. L'azione predefinita per il segnale di riaggancio è terminare il processo, quindi dobbiamo fornire un gestore di segnale per catturare il segnale. Ci aspettiamo quindi che printf nella funzione sig_hup appaia prima di printf nella funzione pr_ids.


Soluzione 3:

Ho eseguito alcuni test utilizzando CentOS 7.1 e bash. Nota questo significa huponexit è off per impostazione predefinita ed è stato disattivato per la maggior parte dei miei test.

Hai bisogno nohup quando inizi un lavoro in un terminale, perché se chiudi quel terminale senza uscire dalla shell in modo pulitoil terminale invia a bash il segnale SIGHUP alla shell, che poi lo invia a tutti i figli. Se esci dalla shell in modo pulito, il che significa che il lavoro deve essere già in background in modo da poter digitare exit o premi Control-D al prompt dei comandi: nessun segnale di alcun tipo viene inviato al lavoro in background da bash.

Test:

Terminale 1

$ echo $$
16779

Terminale 2

$ strace -e signal -p16779
Process 16779 attached

(chiudere il morsetto 1, visto nel morsetto 2):

--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16777, si_uid=3000090} ---
rt_sigprocmask(SIG_BLOCK, [CHLD TSTP TTIN TTOU], [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], NULL, 8) = 0
rt_sigaction(SIGHUP, {SIG_DFL, [], SA_RESTORER, 0x7f7ace3d9a00}, {0x456880, [HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], SA_RESTORER, 0x7f7ace3d9a00}, 8) = 0
kill(16779, SIGHUP)                     = 0
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=16779, si_uid=3000090} ---
+++ killed by SIGHUP +++

Lavoro doit.sh:

#!/bin/bash

imhupped() {
        echo "HUP" >> /tmp/outfile
}

trap imhupped SIGHUP

for i in $(seq 1 6); do echo out $i >> /tmp/outfile; sleep 5; done

Avvialo in background nel Terminale 1:

Terminale 1

$ ./doit.sh &
[1] 22954

Straccialo nel Terminal 2; chiudi il Terminal 1 dopo un paio di loop:

Terminale 2

$ strace -e signal -p22954
Process 22954 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=22980, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f7a5d547a00}, {0x43e4b0, [], SA_RESTORER, 0x7f7a5d547a00}, 8) = 0
...
--- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=21685, si_uid=3000090} ---
rt_sigreturn()                          = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=23017, si_status=SIGHUP, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
...

Uscita nel Terminal 3:

Terminale 3

out 1
out 2
out 3
HUP
out 4
out 5
out 6

Tuttavia, se esci bash, esce semplicemente senza inviare alcun segnale al bambino. Il terminale uscirà perché non ha più un figlio, ma ovviamente non c'è nessuno su HUP perché la shell figlia è già sparita. Il SIGINT, SIG_BLOCK e SIG_SETMASK che vedete sotto sono dovuti al sleep nel guscio.

Terminale 1

$ ./doit.sh &
26275

Terminale 2

$ strace -e signal -p26275
Process 26275 attached
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26280, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0


(..."exit" is typed in bash, notice no new signals sent...)


rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26303, si_status=0, si_utime=0, si_stime=0} ---
rt_sigreturn()                          = 0
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {0x43e4b0, [], SA_RESTORER, 0x7f5edd3a5a00}, {SIG_DFL, [], SA_RESTORER, 0x7f5edd3a5a00}, 8) = 0

Terminale 3, uscita

out 1
out 2
out 3
out 4
out 5
out 6

È interessante notare che ho impostato huponexit essere d'accordo shopt -s huponexit; shopt (quest'ultimo ha effettuato la revisione), quindi ha eseguito l'ultimo test e di nuovo bash non ha inviato alcun segnale al processo in background. Ancora PIÙ interessante, come abbiamo visto bash fatto invia il segnale al processo in background dopo averlo ricevuto da un terminale che si è chiuso in faccia. Sembra come se huponexit non aveva alcun rapporto in un modo o nell'altro.

Spero che questo rimuova qualsiasi mistero o confusione riguardante almeno l'huppiness di bash, su quando e come viene inviato il segnale HUP. Almeno i miei test erano completamente riproducibili, per me. Sarei interessato a sapere se ci sono altre impostazioni che potrebbero influenzare il comportamento di bash.

E, come sempre, YSMV (Your Shell May Vary).

Addendum 1

Quando eseguo una shell come exec /bin/shquindi eseguire lo script come /bin/sh ./doit.sh &quindi esci dalla shell in modo pulito, non vengono inviati segnali al processo in background e continua a essere eseguito fino al completamento.

Addendum 2

Quando eseguo una shell come exec /bin/cshquindi eseguire lo script come /bin/sh ./doit.sh &quindi esci dalla shell in modo pulito, non vengono inviati segnali al processo in background e continua a essere eseguito fino al completamento.

Ricorda qualcosa, che hai la possibilità di aggiungere un'accusa di successo.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.