¿Por qué no funcionó Ctrl-C?

¿Por qué no funcionó Ctrl-C?

Acabo de golpear Ctrlcdos veces mi caparazón en un intento de detener un proceso que está tardando mucho en finalizar.

^CSe repitió dos veces, pero el proceso continuó.

¿Por qué no Ctrlcabandonó el proceso como lo hace normalmente?

Respuesta1

Los procesos pueden optar por:

  • ignore la señal SIGINT que generalmente se envía al presionar Ctrl-C(como trap '' INTen un shell) o tenga su propio controlador que decida no terminar (o no termine de manera oportuna).
  • decirle al dispositivo terminal que el carácter que hace que se envíe un SIGINT al trabajo de primer plano es otra cosa (como en stty int '^K'un shell)
  • decirle al dispositivo terminal que no envíe ninguna señal (como stty -isigen un shell).

O pueden ser ininterrumpibles, como cuando se encuentra en medio de una llamada al sistema que no se puede interrumpir.

En Linux (con un kernel relativamente reciente), puede saber si un proceso está ignorando y/omanejoSIGINT mirando la salida de

$ kill -l INT
2
$ grep Sig "/proc/$pid/status"
SigQ:   0/63858
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000002
SigCgt: 0000000000000000

SIGINT es 2. El segundo bit de SigIgn anterior es 1, lo que significa que se ignora SIGINT.

Puedes automatizar eso con:

$ SIG=$(kill -l INT) perl -lane 'print $1 if $F[0] =~ /^Sig(...):/ && 
    $F[1] & (1<<($ENV{SIG}-1))' < "/proc/$pid/status"
Ign

Para comprobar cuál es el carácter actual intro si isigestá habilitado para un terminal determinado:

$ stty -a < /dev/pts/0
[...] intr = ^C [...] isig

(arriba del intrcarácter está ^C(el carácter que generalmente envía su terminal (emulador) al presionar CTRL-Cy las señales de entrada no están deshabilitadas.

$ stty -a < /dev/pts/1
[...] intr = ^K [...] -isig

( intrel personaje está ^Ky isigestá deshabilitado para /dev/pts/1).

Para completar, hay otras dos formas en que un proceso puede hacer algo para dejar de recibir SIGINT, aunque eso no es algo que normalmente vería.

Tras Ctrl+C, la señal SIGINT se envía a todos los procesos en elgrupo de procesos en primer plano del terminal. Generalmente es el shell el que coloca los procesos en grupos de procesos (asignados al shelltrabajos) e indique al dispositivo terminal cuál es elprimer planouno.

Ahora un proceso podría:

  • Salga de su grupo de procesos. Si se mueve a otro grupo de procesos (cualquier grupo de procesos excepto el que es elprimer planouno), entonces ya no recibirá el SIGINT Ctrl-C(ni las otras señales relacionadas con el teclado como SIGTSTP, SIGQUIT). Sin embargo, podría suspenderse si intentara leer (posiblemente también escribir dependiendo de la configuración del dispositivo terminal) desde el dispositivo terminal (como lo hacen los procesos en segundo plano).

    Como ejemplo:

    perl -MPOSIX -e 'setpgid(0,getppid) or die "$!"; sleep 10'
    

    no podría ser interrumpible con Ctrl-C. Lo anterior perlintentará unirse al grupo de procesos cuyo ID es el mismo que el ID del proceso principal. En general, no hay garantía de que exista un grupo de procesos con esa identificación. Pero aquí, en el caso de que el perlcomando se ejecute solo en el indicador de un shell interactivo, el ppid será el proceso del shell y el shell normalmente se habrá iniciado en su propio grupo de procesos.

    Si el comando aún no es un líder de grupo de procesos (el líder de ese grupo de procesos en primer plano), iniciar un nuevo grupo de procesos tendría el mismo efecto.

    Por ejemplo, dependiendo del caparazón,

    $ ps -j >&2 | perl -MPOSIX -e 'setpgid(0,0) or die "$!"; sleep 10'
      PID  PGID   SID TTY          TIME CMD
    21435 21435 21435 pts/12   00:00:00 zsh
    21441 21441 21435 pts/12   00:00:00 ps
    21442 21441 21435 pts/12   00:00:00 perl
    

    tendría el mismo efecto. psy perlse inician en el grupo de procesos de primer plano, pero en la mayoría de los shells, pssería el líder de ese grupo (como se ve en el psresultado anterior donde el pgid de ambos psy perles el pid de ps), por lo que perlpuede iniciar su propio grupo de procesos.

  • O podría cambiar el grupo de procesos de primer plano. Básicamente, dígale al dispositivo tty que envíe el SIGINT a algún otro grupo de procesos alCtrl+C

    perl -MPOSIX -e 'tcsetpgrp(0,getppid) or die$!; sleep 5'
    

    Allí, perlpermanece en el mismo grupo de procesos, pero en lugar de eso le dice al dispositivo terminal que el grupo de procesos en primer plano es aquel cuyo ID es el mismo que su ID de proceso principal (consulte la nota anterior sobre eso).

información relacionada