Como o sudo é interrompido no xterm no Ctrl-C? [duplicado]

3

Por favor, explique em detalhes (incluindo tty material relacionado) como é que um sudo processo de primeiro plano em um emulador de terminal X realmente matou no Ctrl-C .

Veja o seguinte exemplo, por favor:

$ sudo -u test_no_pw sleep 999 &                                    
[1] 16657                  
$ ps -o comm,pid,ppid,ruid,rgid,euid,egid,suid,sgid,sid,pgid -t
COMMAND           PID  PPID  RUID  RGID  EUID  EGID  SUID  SGID   SID  PGID
zsh             15254 15253  1000  1000  1000  1000  1000  1000 15254 15254
sudo            16657 15254     0  1000     0  1000     0  1000 15254 16657
sleep           16658 16657  1002  1002  1002  1002  1002  1002 15254 16657
ps              16660 15254  1000  1000  1000  1000  1000  1000 15254 16660
$ fg
[1]  + running    sudo -u test_no_pw sleep 999
^C
$ # it was killed

Antes de interromper o sudo , iniciei o strace em outro terminal:

# strace -p 16657
Process 16657 attached
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL, si_value={int=809122100, ptr=0x54552036303a3934}} ---
[...SNIP...]

Então o remetente é SI_KERNEL , interessante. Perguntei ontem nos canais de IRC e pesquisei no Google, mas recebi apenas respostas nebulosas ou incorretas. A maioria das pessoas disse que o terminal ou o shell enviará o SINGINT para o sudo, mas parece que ele não pode acontecer de acordo com kill(2) :

For a process to have permission to send a signal it must either be privileged (under Linux: have the CAP_KILL capability), or the real or effective user ID of the sending process must equal the real or saved set-user-ID of the target process. In the case of SIGCONT it suffices when the sending and receiving processes belong to the same session. (Historically, the rules were different; see NOTES.)

Eu prevejo que terá algo a ver com o envio de uma seqüência de escape com ASCII ETX (3) para um pseudo-terminal, mas estou longe de entendê-lo. (Por que o sinal é originado do kernel?)

Relacionado, mas nebuloso / incorreto:

Estou mais interessado em saber como funciona no Linux.

    
por woky 26.12.2015 / 23:58

1 resposta

3

(Esta é uma tentativa de esclarecer e responder a pergunta, mas melhorias e correções são bem-vindas).

Primeiro, vamos remover o sudo e o & + fg do cenário - já que eles não estão afetando a estação (eu presumi que você os usou principalmente para obter o PID). A questão então se torna: 1) como um processo rodando em primeiro plano de um terminal recebe SIGINT; 2) o que muda quando o terminal é um pseudo-terminal usando X11 (por exemplo, Xterm).

  1. A entrega de SIGINT (e SIGQUIT, SIGTSTP) é gerada pelo driver de terminal de controle do kernel, quando ele intercepta um caractere CTRL-C, e é por isso que você vê SI_KERNEL como a origem. Isso acontece independentemente do X11 ou dos pseudo-terminais. É bem ilustrado em "Programação Avançada no Unix Environment 2nd Edition (APUE2)", Figura 9.7, página 272 (não vou colá-lo aqui por motivos de copyright, mas tenho certeza que ele pode ser encontrado). É explicado na página 275, seção "9.8 Job Control". O código relevante do kernel do Linux é provavelmente o seguinte: link

  2. Agora adicionando pseudo-terminais à mixagem: o código do kernel do psudeo-terminal ainda usa o código de terminal padrão (mencionado acima) - assim quando o lado 'mestre' do PTY (o X-terminal) recebe o X11 key-event de "CTRL-C", e envia para o escravo PTY, o caractere é detectado pelo drive do terminal do kernel, e envia SIGINT para o grupo de processos em primeiro plano (sudo no seu caso). Isso é ilustrado em APUE2, Figura 19.1, página 676.

Na página APUE2 706 há um pequeno parágrafo "Geração de Sinal" mencionando que os sinais podem ser enviados diretamente pelo mestre PTY usando ioctl(2) (por exemplo, link ), mas acredito que este não é o caso aqui.

Comentários bem-vindos.

    
por 27.12.2015 / 01:27