O que as shells interativas devem fazer nos grupos de processos órfãos?

9

(Poste novamente no unix de acordo com a sugestão em link )

A pergunta curta é: o que um shell deve fazer se estiver em um grupo de processos órfão que não possui o tty? Mas eu recomendo ler a longa pergunta porque é divertido.

Aqui está uma maneira divertida e empolgante de transformar seu laptop em um aquecedor de ambiente portátil, usando seu shell favorito (a menos que você seja um desses estranhos tcsh):

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

Isso faz com que o bash ligue a CPU em 100%. zsh e fish fazem o mesmo, enquanto ksh e tcsh murmuram algo sobre o controle do job e depois chilam, o que é um pouco melhor, mas não muito. Ah, e é um infrator agnóstico de plataforma: OS X e Linux são afetados.

Minha explicação (potencialmente errada) é a seguinte: o shell filho detecta que não está em primeiro plano: tcgetpgrp(0) != getpgrp() . Portanto, ele tenta parar por si mesmo: killpg(getpgrp(), SIGTTIN) . Mas seu grupo de processos é órfão, porque seu pai (o programa C) era o líder e morreu, e SIGTTIN enviado para um grupo de processos órfãos acabou de ser descartado (caso contrário, nada poderia iniciá-lo novamente). Portanto, o shell filho não é interrompido, mas ainda está em segundo plano, portanto, ele faz tudo novamente, imediatamente. Enxagúe e repita.

Minha pergunta é: como um shell de linha de comando pode detectar esse cenário e qual é a coisa certa a fazer? Eu tenho duas soluções, nenhuma das quais é ideal:

  1. Tente sinalizar o processo cujo pid corresponde ao nosso ID do grupo. Se isso falhar com ESRCH , isso significa que provavelmente somos órfãos.
  2. Experimente uma leitura sem bloqueio de um byte de /dev/tty . Se isso falhar com EIO , isso significa que provavelmente somos órfãos.

(Nosso problema de rastreamento é link )

Obrigado por seus pensamentos!

    
por ridiculous_fish 29.12.2012 / 20:28

1 resposta

3

Concordo com sua análise e concordo que parece que você precisa detectar se seu grupo de processos está órfão ou não.

tcsetattr também deve retornar EIO se o grupo de processos é órfão (e não estamos bloqueando / ignorando SIGTT OU . Essa pode ser uma maneira menos intrusiva que um read no terminal.

Note que você pode reproduzi-lo com:

(bash<&1 &)

Você precisa do redirecionamento, caso contrário, o stdin é redirecionado para / dev / null ao executar um comando em segundo plano.

(bash<&1 & sleep 2)

Dá um comportamento ainda mais estranho, porque você acaba com dois shells lendo no terminal. Eles estão ignorando SIGTTIN e o novo não está detectando, uma vez iniciado, ele não está mais no grupo de processos em primeiro plano.

A solução de pde ksh93 não é tão ruim: apenas vá até 20 vezes (em vez de infinito) através desse loop antes de desistir.

    
por 30.12.2012 / 09:01