Cosa dovrebbero fare le shell interattive nei gruppi di processi orfani?


10

(Ripubblicazione in unix per il suggerimento in /programming/13718394/what-should-interactive-shells-do-in-orphaned-process-groups )

La domanda breve è: cosa dovrebbe fare una shell se si trova in un gruppo di processi orfani che non possiede il tty? Ma raccomando di leggere la lunga domanda perché è divertente.

Ecco un modo divertente ed eccitante per trasformare il tuo laptop in un riscaldatore di spazio portatile, usando la tua shell preferita (a meno che tu non sia uno di quei bizzarri tcsh):

#include <unistd.h>   
int main(void) {
    if (fork() == 0) {
        execl("/bin/bash", "/bin/bash", NULL);
    }
    return 0;
}

Questo fa sì che bash tocchi la CPU al 100%. zsh e fish fanno lo stesso, mentre ksh e tcsh mormorano qualcosa sul controllo del lavoro e poi si chinano, il che è un po 'meglio, ma non molto. Oh, ed è un offensore agnostico della piattaforma: OS X e Linux sono entrambi colpiti.

La mia (potenzialmente sbagliato) spiegazione è la seguente: il guscio bambino rileva che non è in primo piano: tcgetpgrp(0) != getpgrp(). Quindi cerca di fermare se stesso: killpg(getpgrp(), SIGTTIN). Ma il suo gruppo di processo è rimasto orfano, perché il suo genitore (il programma C) era il leader ed è morto, e SIGTTINinviato a un gruppo di processi orfano è appena stato eliminato (altrimenti nulla potrebbe riavviarlo). Pertanto, la shell figlio non viene arrestata, ma è ancora in background, quindi esegue di nuovo tutto immediatamente. Risciacqua e ripeti.

La mia domanda è: come può una shell da riga di comando rilevare questo scenario e qual è la cosa giusta da fare? Ho due soluzioni, nessuna delle quali è l'ideale:

  1. Prova a segnalare il processo il cui pid corrisponde al nostro ID gruppo. Se fallisce ESRCH, significa che probabilmente siamo orfani.
  2. Prova una lettura non bloccante di un byte da /dev/tty. Se fallisce EIO, significa che probabilmente siamo orfani.

(Il nostro problema di tracciamento è https://github.com/fish-shell/fish-shell/issues/422 )

Grazie per i tuoi pensieri!

Risposte:


4

Sono d'accordo con la tua analisi e sono d'accordo che sembra che tu debba rilevare se il tuo gruppo di processi è orfano o meno.

tcsetattrè anche pensato per tornare EIOse il gruppo di processi è orfano (e non stiamo bloccando / ignorando OU SIGTT . Potrebbe essere un modo meno invadente di un readterminale.

Nota che puoi riprodurlo con:

(bash<&1 &)

È necessario il reindirizzamento, altrimenti lo stdin viene reindirizzato su / dev / null quando si esegue un comando in background.

(bash<&1 & sleep 2)

Fornisce un comportamento ancora più strano, come se finissi con due shell leggere dal terminale. Stanno ignorando SIGTTINe il nuovo non sta rilevando, una volta iniziato che non è più nel gruppo di processi in primo piano.

ksh93La soluzione non è poi così male: vai solo fino a 20 volte (anziché infinito) attraverso quel ciclo prima di arrenderti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.