Warum hat Strg-C nicht funktioniert?

Warum hat Strg-C nicht funktioniert?

Ich habe gerade Ctrlczweimal auf meine Shell geschlagen, um einen Vorgang anzuhalten, der sehr lange dauert.

^Cwurde zweimal wiederholt, aber der Vorgang ging einfach weiter.

Warum wurde Ctrlcder Vorgang nicht wie gewohnt beendet?

Antwort1

Prozesse können Folgendes wählen:

  • Ignorieren Sie das SIGINT-Signal, das normalerweise beim Drücken gesendet wird Ctrl-C(wie trap '' INTin einer Shell), oder verfügen Sie über einen eigenen Handler dafür, der sich entscheidet, nicht zu beenden (oder nicht rechtzeitig zu beenden).
  • dem Endgerät mitteilen, dass das Zeichen, das die Übermittlung eines SIGINT an den Vordergrundjob bewirkt, ein anderes ist (wie in stty int '^K'einer Shell)
  • sagen Sie dem Endgerät, dass es kein Signal senden soll (wie stty -isigin einer Shell).

Oder sie können nicht unterbrechungsfähig sein, beispielsweise mitten in einem Systemaufruf, der nicht unterbrochen werden kann.

Unter Linux (mit einem relativ neuen Kernel) können Sie erkennen, ob ein ProzessHandhabungSIGINT durch Betrachten der Ausgabe von

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

SIGINT ist 2. Das zweite Bit von SigIgn oben ist 1, was bedeutet, dass SIGINT ignoriert wird.

Sie können dies automatisieren mit:

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

So prüfen Sie, welches das aktuelle intrZeichen ist oder ob isiges für ein bestimmtes Terminal aktiviert ist:

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

(über dem intrZeichen steht ^C(das Zeichen, das normalerweise von Ihrem Terminal (Emulator) gesendet wird, wenn Sie drücken CTRL-Cund die Eingabesignale nicht deaktiviert sind.

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

( intrZeichen ist ^Kund isigist deaktiviert für /dev/pts/1).

Der Vollständigkeit halber sei erwähnt, dass es noch zwei weitere Möglichkeiten gibt, wie ein Prozess den Empfang von SIGINTs beenden kann. Dies ist jedoch nichts, was man normalerweise sieht.

Daraufhin Ctrl+Cwird das Signal SIGINT an alle Prozesse imVordergrundprozessgruppe des Terminals. Normalerweise ist es die Shell, die Prozesse in Prozessgruppen einordnet (abgebildet auf ShellArbeitsplätze) und teilen Sie dem Endgerät mit, welchesVordergrundeins.

Nun könnte ein Prozess:

  • Verlassen Sie die Prozessgruppe. Wenn es in eine andere Prozessgruppe wechselt (jede andere als die, die dieVordergrundeins), dann empfängt es nicht mehr das SIGINT Ctrl-C(und auch keine anderen tastaturbezogenen Signale wie SIGTSTP, SIGQUIT). Es könnte jedoch angehalten werden, wenn es versucht, vom Terminalgerät zu lesen (und je nach den Einstellungen des Terminalgeräts möglicherweise auch zu schreiben) (wie es Hintergrundprozesse tun).

    Als Beispiel:

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

    konnte nicht unterbrochen werden mit Ctrl-C. Oben perlwird versucht, der Prozessgruppe beizutreten, deren ID mit der ID des übergeordneten Prozesses übereinstimmt. Im Allgemeinen gibt es keine Garantie dafür, dass es eine solche Prozessgruppe mit dieser ID gibt. Aber hier, im Fall dieses perlBefehls, der allein an der Eingabeaufforderung einer interaktiven Shell ausgeführt wird, ist die ppid der Prozess der Shell und die Shell wurde normalerweise in ihrer eigenen Prozessgruppe gestartet.

    Wenn der Befehl nicht bereits ein Prozessgruppenleiter ist (der Leiter dieser Vordergrundprozessgruppe), hätte das Starten einer neuen Prozessgruppe dieselbe Wirkung.

    Je nach Shell beispielsweise

    $ 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
    

    hätte dieselbe Wirkung. psund perlwerden in der Vordergrundprozessgruppe gestartet, pswäre aber auf den meisten Shells der Anführer dieser Gruppe (wie in der psAusgabe oben zu sehen ist, wo die pgid sowohl von psals auch perldie pid von ist ps), perlkann also seine eigene Prozessgruppe starten.

  • Oder es könnte die Vordergrund-Prozessgruppe ändern. Sagen Sie dem TTY-Gerät im Grunde, dass es das SIGINT an eine andere Prozessgruppe senden soll, wennCtrl+C

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

    Dort perlbleibt es in derselben Prozessgruppe, teilt dem Endgerät jedoch stattdessen mit, dass die Vordergrundprozessgruppe diejenige ist, deren ID mit der ID ihres übergeordneten Prozesses übereinstimmt (siehe Anmerkung oben).

verwandte Informationen