Perché non è possibile uscire con Cc?


20

Il programma ed, un editor di testo minimo, non può essere chiuso inviandogli un interrupt tramite Ctrl- C, invece stampando il messaggio di errore "?" alla console. Perché non edesce solo quando riceve l'interrupt? Sicuramente non c'è motivo per cui un messaggio di errore criptico sia più utile qui che semplicemente uscire. Questo comportamento porta molti nuovi utenti nel seguente tipo di interazione:

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed

Uno spreco così tragico, facilmente evitabile se fosse edsemplicemente accettato di essere interrotto.

Un altro programma testardo che mostra un comportamento simile è lessche non sembra avere molte ragioni per ignorarlo C-c. Perché questi programmi non danno solo un suggerimento?


4
Le applicazioni interattive non sono le stesse di non interattive. Il comportamento Ctrl-C a cui sei abituato è quello predefinito per quelli non interattivi. Quelli interattivi possono ignorare il comportamento di Ctrl-C per i propri scopi.
jw013,

4
Inoltre, non sono sicuro se scherzo
jw013

@ jw013 Sì, la "sessione tipica" era uno scherzo (non ho potuto trovarlo per qualche motivo) ma la mia domanda è seria. Quello che non capisco è perché queste applicazioni scelgono di sovrascrivere il comportamento di Ctrl-C se in realtà non fornisce nulla di utile.
Lily Chung,

1
Poiché questa domanda si presenta come una delle migliori risposte di ricerca di Google a "come uscire da", vorrei aggiungere qui che è solo 'q' seguito da un ritorno. Molti Bothan sono morti per portarci queste informazioni.
Dmitri

Risposte:


19

Ctrl+ Cinvia SIGINT . L'azione convenzionale per SIGINT è di tornare al ciclo di livello superiore di un programma, annullando il comando corrente ed entrando in una modalità in cui il programma attende il comando successivo. Solo i programmi non interattivi dovrebbero morire di SIGINT.

Quindi è naturale che Ctrl+ Cnon uccida, ma lo ritorni al suo ciclo di livello superiore. Ctrl+ Cinterrompe la riga di input corrente e ritorna al prompt ed.

Lo stesso vale per meno: Ctrl+ Cinterrompe il comando corrente e riporta al prompt dei comandi.

Per motivi storici, ed ignora SIGQUIT ( Ctrl+ \). Le applicazioni normali non dovrebbero catturare questo segnale e consentire a se stesse di essere terminate, con un core dump se abilitato.


@Kzqai No, le normali applicazioni non dovrebbero catturare SIGQUIT, è inteso come un'uscita di emergenza.
Gilles 'SO- smetti di essere malvagio' il

Ah, capito. Va bene, retratto.
Kzqai,

18

Il codice sorgente Unix V7ed(1) è un programma C primitivo di 1.762 righe con pochi commenti, uno dei quali è questo commento di intestazione altamente illuminante:

/*
 * Editor
 */

Dato che il codice sorgente stesso non fornisce alcuna logica, lo otterrai solo dall'autore del programma.

edè stato originariamente scritto da Ken Thompson nell'assemblea PDP-11 , ma in realtà avresti bisogno di parlare con chiunque lo portasse a C. Potrebbe essere stato Dennis Ritchie , da quando ha creato C per Unix, ed è stato uno dei tanti che hanno usato C per rendere Unix portabile su macchine non PDP. Il dottor Ritchie non è più in giro per rispondere a tali domande.

La mia lettura del codice suggerisce che è stato fatto per cercare di preservare il contenuto della copia in-core del documento modificato. Noterai che anche altri editor di testo non muoiono Ctrl-C.

Ecco cosa edfa su Ctrl-C:

onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}

(Sì, K&R C. Non abbiamo bisogno di specificatori del tipo restituito di Steenkin o dichiarazioni di parametri.)

Tradotto in inglese ed,:

  1. Registra nuovamente il gestore del segnale.

    (Unix non ha ricevuto segnali di auto-reset fino a 4.3BSD , a metà degli anni '80.)

  2. Scrive una nuova riga e ricorda di averlo fatto tramite la variabile globale lastc.

    ( ed.cha circa sessanta variabili globali).

  3. Chiama la error()funzione, che notoriamente fa poco più che stampare ?, dal punto di vista dell'utente.

In altre parole, sta dicendo: "Non volevi davvero farlo, vero?"


2
Vale anche la pena notare che molti editor di testo non escono da Control-C. Anche Vim no. Nemmeno nano. Nemmeno io penso che emacs lo faccia, ma non l'ho installato per testarlo.
derobert,

3
@derobert Vi tratta Ctrl + C in modo Unix: torna al livello superiore. Emacs ha le sue combinazioni di tasti, a causa delle sue origini non Unix; l'equivalente di Emacs di Ctrl + C di Unix è Ctrl + G (il carattere della campana - suona la campana al computer per interromperla)
SO di Gilles- smetti di essere malvagio '

@derobert: punto giusto. Ho aggiunto questo alla risposta.
Warren Young,

2
@Gilles: Uno degli effetti collaterali di chiamare error(s)in ed.cè quello di tornare al ciclo di elaborazione principale. Lo fa con una longjmp()chiamata. brivido
Warren Young,

1
Grazie per i dettagli e la lezione di storia. Questa è stata un'ottima lettura!
alichaudry,

7

ed, come altri programmi interattivi, usa Ctrl+ Cper interrompere le attività del programma stesso.
Questo è molto simile al caso normale, in cui interrompe un'attività in esecuzione nella shell: un comando.

Dal punto di vista dell'utente, entrambe le varianti sono molto simili. La gestione del segnale è diversa: nel solito caso, il segnale SIGINTviene inviato al processo in primo piano, un comando in esecuzione e il comando lo gestisce uscendo.
Nel caso di ed, il segnale viene inviato al processo in primo piano, l' edistanza. Se è in esecuzione un'attività ed, viene interrotta e viene visualizzato il prompt. Se non è in esecuzione alcuna attività, non viene modificato nulla.

Nota come anche una shell non esce su Ctrl+ C, proprio come ed. E che esce su Ctrl+ D. Ancora una volta, proprio comeed


3

Ci sono tre segnali che si edpreoccupano:

  1. INT
  2. HUP
  3. QUIT

La specifica POSIX died dice quanto segue su questi:

SIGINT

L' edutilità deve interrompere l'attività corrente, scrivere la stringa ?\nsull'output standard e tornare alla modalità di comando (consultare la sezione DESCRIZIONE ESTESA).

SIGHUP

Se il buffer non è vuoto ed è cambiato dall'ultima scrittura, l' edutilità deve tentare di scrivere una copia del buffer in un file. Innanzitutto, ed.hupdeve essere utilizzato il file indicato nella directory corrente; in caso contrario, verrà utilizzato il file indicato ed.hupnella directory indicata dalla HOMEvariabile d'ambiente. In ogni caso, l' edutilità deve uscire senza scrivere il file nel percorso attualmente memorizzato e senza tornare alla modalità di comando.

SIGQUIT

L' edutilità deve ignorare questo evento.

Quindi, qualunque implementazione edtu stia usando, è conforme alle specifiche POSIX per quanto riguarda il INTsegnale (che è ciò che Ctrl+Cinvia).

A questo proposito, l'editor si comporta come una shell interattiva, che inoltre non termina alla ricezione del INTsegnale. Altri editor, come vie nanofanno la stessa cosa.


1
Alcune implementazioni del programma contraddicono deliberatamente POSIX, quindi potrebbe essere utile spiegare la logica dello standard / il costo della violazione in questo caso. stackoverflow.com/questions/38605463/...
sourcejedi

1
@sourcejedi Lo standard non dice nulla sui segnali nella sua logica. Non ho trovato alcuna logica che dica qualcosa sul perché lo standard sia seguito nelle fonti edche ho a disposizione. Si comporta in modo simile alla shell, che inoltre non termina con la ricezione del INTsegnale.
Kusalananda
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.