Bagaimana SIGINT berhubungan dengan sinyal terminasi lainnya seperti SIGTERM, SIGQUIT dan SIGKILL?

103

Pada sistem POSIX, sinyal terminasi biasanya memiliki urutan berikut (menurut banyak halaman MAN dan Spec POSIX):

  1. SIGTERM - dengan sopan meminta proses untuk dihentikan. Ini akan berakhir dengan anggun, membersihkan semua sumber daya (file, soket, proses anak, dll.), Menghapus file sementara dan sebagainya.

  2. SIGQUIT - permintaan yang lebih kuat. Ini akan menghentikan ungraceful, masih membersihkan sumber daya yang benar-benar membutuhkan pembersihan, tapi mungkin tidak menghapus file sementara, mungkin menulis informasi debug di suatu tempat; pada beberapa sistem juga akan ditulis core dump (terlepas dari apakah sinyal ditangkap oleh aplikasi atau tidak).

  3. SIGKILL - permintaan paling kuat. Proses tersebut bahkan tidak diminta untuk melakukan apapun, tetapi sistem akan membersihkan proses tersebut, apakah seperti itu atau tidak. Kemungkinan besar dump inti ditulis.

Bagaimana SIGINT cocok dengan gambaran itu? Proses CLI biasanya dihentikan oleh SIGINT ketika pengguna menekan CRTL + C, namun proses latar belakang juga dapat dihentikan oleh SIGINT menggunakan utilitas KILL. Apa yang tidak dapat saya lihat di spesifikasi atau file header adalah jika SIGINT lebih atau kurang kuat daripada SIGTERM atau jika ada perbedaan antara SIGINT dan SIGTERM sama sekali.

MEMPERBARUI:

Deskripsi terbaik tentang sinyal terminasi yang saya temukan sejauh ini ada di Dokumentasi GNU LibC . Ini menjelaskan dengan sangat baik bahwa ada perbedaan yang diinginkan antara SIGTERM dan SIGQUIT.

Dikatakan tentang SIGTERM:

Ini adalah cara normal untuk meminta penghentian program dengan sopan.

Dan dikatakan tentang SIGQUIT:

[...] dan menghasilkan core dump ketika menghentikan proses, seperti sinyal kesalahan program. Anda dapat menganggap ini sebagai kondisi kesalahan program yang “terdeteksi” oleh pengguna. [...] Jenis pembersihan tertentu sebaiknya diabaikan dalam menangani SIGQUIT. Misalnya, jika program membuat file sementara, program harus menangani permintaan penghentian lainnya dengan menghapus file sementara. Tetapi lebih baik bagi SIGQUIT untuk tidak menghapusnya, sehingga pengguna dapat memeriksanya sehubungan dengan core dump.

Dan SIGHUP juga dijelaskan dengan cukup baik. SIGHUP sebenarnya bukan sinyal penghentian, itu hanya berarti "koneksi" ke pengguna telah terputus, jadi aplikasi tidak dapat mengharapkan pengguna untuk membaca keluaran lebih lanjut (mis. Stdout / stderr output) dan tidak ada masukan yang diharapkan dari pengguna lagi. Untuk sebagian besar aplikasi, itu berarti lebih baik berhenti. Secara teori, aplikasi juga dapat memutuskan bahwa ia masuk ke mode daemon saat SIGHUP diterima dan sekarang berjalan sebagai proses latar belakang, menulis keluaran ke file log yang dikonfigurasi. Untuk kebanyakan daemon yang sudah berjalan di latar belakang, SIGHUP biasanya berarti bahwa mereka harus memeriksa ulang file konfigurasinya, jadi Anda mengirimkannya ke proses latar belakang setelah mengedit file konfigurasi.

Namun tidak ada penjelasan yang berguna tentang SIGINT di halaman ini, selain yang dikirimkan oleh CRTL + C. Apakah ada alasan mengapa seseorang menangani SIGINT dengan cara yang berbeda dari SIGTERM? Jika demikian alasan apa ini dan bagaimana penanganannya akan berbeda?

Mecki
sumber
1
Pertanyaan bagus. Saya menduga beberapa bagian dari sejarah Unix akan terlibat dalam jawabannya.
Alex B
Saya tahu pertanyaan ini sudah lama, tetapi jika ada yang datang ke sini untuk daftar lengkap sinyal untuk OS (Linux) Anda, mereka dapat ditemukan dengan mengetik sudo fuser -ldi command prompt Anda. Bagi saya ini menunjukkan:HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED
Nick Bull
3
Coba juga kill -ldaftar sinyal.
AAAfarmclub

Jawaban:

88

SIGTERM dan SIGKILL dimaksudkan untuk permintaan "hentikan proses ini" tujuan umum. SIGTERM (secara default) dan SIGKILL (selalu) akan menyebabkan penghentian proses. SIGTERM dapat ditangkap oleh proses (misalnya, sehingga dapat melakukan pembersihan sendiri jika diinginkan), atau bahkan diabaikan sepenuhnya; tetapi SIGKILL tidak dapat ditangkap atau diabaikan.

SIGINT dan SIGQUIT ditujukan khusus untuk permintaan dari terminal: karakter input tertentu dapat ditetapkan untuk menghasilkan sinyal ini (tergantung pada pengaturan kontrol terminal). Tindakan default untuk SIGINT adalah jenis penghentian proses yang sama sebagai tindakan default untuk SIGTERM dan tindakan yang tidak dapat diubah untuk SIGKILL; tindakan default untuk SIGQUIT juga penghentian proses, tetapi tindakan yang ditentukan implementasi tambahan mungkin terjadi, seperti pembuatan core dump. Entah dapat ditangkap atau diabaikan oleh proses jika diperlukan.

SIGHUP, seperti yang Anda katakan, dimaksudkan untuk menunjukkan bahwa koneksi terminal telah terputus, bukan sebagai sinyal terminasi. Tapi, sekali lagi, tindakan default untuk SIGHUP (jika proses tidak menangkap atau mengabaikannya) adalah menghentikan proses dengan cara yang sama seperti SIGTERM dll.

Ada tabel dalam definisi POSIXsignal.h yang mencantumkan berbagai sinyal serta tindakan dan tujuan defaultnya, dan bab Antarmuka Terminal Umum menyertakan lebih banyak detail tentang sinyal yang berhubungan dengan terminal.

Matthew Slattery
sumber
10
Ini adalah poin kuncinya: SIGINT dan SIGQUIT dapat dibuat dari terminal dengan menggunakan karakter tunggal, saat program sedang berjalan. Sinyal lain harus dihasilkan oleh program lain, entah bagaimana (misalnya dengan perintah kill). SIGINT tidak sekeras SIGQUIT; yang terakhir menghasilkan core dump. SIGKILL tidak dapat dijebak. SIGHUP dibuat jika koneksi Anda terputus (jendela ditutup, dll). Jadi, semuanya memiliki arti yang berbeda.
Jonathan Leffler
TTY Demystified memiliki beberapa informasi yang mudah dicerna tentang bagaimana sinyal berinteraksi dengan subsistem tty dari kernel. Menambahkan beberapa konteks pada jawaban Anda.
Daniel Näslund
2
Sepertinya spesifikasinya tidak terlalu tepat, tetapi pemahaman saya adalah bahwa SIgint meminta program untuk menghentikan tindakannya saat ini, belum tentu berhenti. Untuk program yang hanya dirancang, lakukan satu tindakan per proses yang berarti berhenti, tetapi untuk program interaktif yang memiliki semacam loop read-eval-print, itu bisa berarti menyerah pada eval saat ini dan kembali membaca input pengguna. Saya pikir kurang melakukan itu di sigint.
bdsl
Sinyal apa yang dikirim selama reboot?
Dan Dascalescu
10

Seperti yang dicatat DarkDust banyak sinyal memiliki hasil yang sama, tetapi proses dapat melampirkan tindakan yang berbeda dengan membedakan bagaimana setiap sinyal dihasilkan. Melihat kode sumber kernel FreeBSD (kern_sig.c) saya melihat bahwa dua sinyal ditangani dengan cara yang sama, mereka menghentikan proses dan dikirim ke utas apa pun.

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */
Diomidis Spinellis
sumber
9

man 7 signal

Ini adalah halaman manual non-normatif yang nyaman dari proyek halaman manual Linux yang sering ingin Anda lihat untuk informasi sinyal Linux.

Versi 3.22 menyebutkan hal-hal menarik seperti:

Sinyal SIGKILL dan SIGSTOP tidak dapat ditangkap, diblokir, atau diabaikan.

dan berisi tabel:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process

yang merangkum sinyal Actionyang membedakan misalnya SIGQUIT dari SIGQUIT, karena SIGQUIT memiliki aksi Coredan SIGINT Term.

Tindakan tersebut didokumentasikan dalam dokumen yang sama:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

Term   Default action is to terminate the process.

Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

Saya tidak dapat melihat perbedaan antara SIGTERM dan SIGINT dari sudut pandang kernel karena keduanya memiliki tindakan Termdan keduanya dapat ditangkap. Tampaknya itu hanya "perbedaan konvensi penggunaan umum":

  • SIGINT adalah apa yang terjadi ketika Anda melakukan CTRL-C dari terminal
  • SIGTERM adalah sinyal default yang dikirim oleh kill

Beberapa sinyal ANSI C dan lainnya tidak

Perbedaan yang mencolok adalah:

  • SIGINT dan SIGTERM adalah ANSI C, sehingga lebih portabel
  • SIGQUIT dan SIGKILL tidak

Mereka dijelaskan di bagian "7.14 Penanganan sinyal" dari draft C99 N1256 :

  • Tanda terima SIGINT dari sinyal perhatian interaktif
  • SIGTERM permintaan penghentian dikirim ke program

yang membuat SIGINT menjadi kandidat yang baik untuk Ctrl + C. interaktif

POSIX 7

POSIX 7 mendokumentasikan sinyal dengan signal.hheader: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

Halaman ini juga memiliki tabel minat berikut yang menyebutkan beberapa hal yang telah kami lihat man 7 signal:

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.

BusyBox init

Perintah default BusyBox 1.29.2 rebootmengirimkan SIGTERM ke proses, tidur sebentar, dan kemudian mengirim SIGKILL. Ini tampaknya menjadi konvensi umum di distro yang berbeda.

Saat Anda mematikan sistem BusyBox dengan:

reboot

itu mengirimkan sinyal ke proses init.

Kemudian, penangan sinyal init akhirnya memanggil:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}

yang mencetak ke terminal:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

Berikut adalah contoh konkret minimal dari itu .

Sinyal dikirim oleh kernel

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
8

Setelah pencarian Google cepat untuk sigint vs sigterm , sepertinya satu-satunya perbedaan yang dimaksudkan antara keduanya adalah apakah itu dimulai oleh pintasan keyboard atau dengan panggilan eksplisit ke kill.

Hasilnya, Anda dapat, misalnya, mencegat sigint dan melakukan sesuatu yang istimewa dengannya, mengetahui bahwa kemungkinan besar dikirim melalui pintasan keyboard. Mungkin menyegarkan layar atau sesuatu, bukannya mati (tidak disarankan, karena orang berharap ^Cuntuk mematikan program, hanya sebuah contoh).

Saya juga belajar bahwa ^\seharusnya mengirim sigquit, yang mungkin saya gunakan sendiri. Terlihat sangat berguna.

Jonathan
sumber
3

Menggunakan kill(baik panggilan sistem dan utilitas` Anda dapat mengirim hampir semua sinyal ke proses apa pun, asalkan Anda sudah mendapat izin. Sebuah proses tidak dapat membedakan bagaimana sinyal menjadi hidup dan siapa yang mengirimnya.

Yang sedang berkata, SIGINT benar-benar dimaksudkan untuk menyela interupsi Ctrl-C, sedangkan SIGTERM adalah sinyal terminal umum. Tidak ada konsep sinyal yang "lebih kuat", dengan pengecualian bahwa ada sinyal yang tidak dapat diblokir atau ditangani (SIGKILL dan SIGSTOP, menurut halaman manual).

Sebuah sinyal hanya bisa "lebih kuat" daripada sinyal lain sehubungan dengan bagaimana proses penerimaan menangani sinyal (dan apa tindakan default untuk sinyal itu). Misalnya, secara default, SIGTERM dan SIGINT mengarah ke penghentian. Tetapi jika Anda mengabaikan SIGTERM maka itu tidak akan menghentikan proses Anda, sementara SIGINT masih melakukannya.

DarkDust
sumber
0

Dengan pengecualian beberapa sinyal, penangan sinyal dapat menangkap berbagai sinyal, atau perilaku default setelah menerima sinyal dapat dimodifikasi. Lihat signal(7)halaman manual untuk detailnya.

Ignacio Vazquez-Abrams
sumber
Ya, tetapi jika saya tidak tahu "arti" dari singnal, menangkap sinyalnya tidak ada gunanya, karena saya tidak tahu apa yang harus dilakukan dalam aplikasi saya. GNU C eg menjelaskan perbedaan antara SIGQUIT dan SIGTERM. Tetapi memberikan sedikit informasi tentang SIGINT: gnu.org/s/libc/manual/html_node/Termination-Signals.html
Mecki
" SIGINTSinyal (" program interrupt ") dikirim saat pengguna mengetik karakter INTR (biasanya C-c)." "SIGINT 2 Term Interrupt from keyboard" Anda menekan Ctrl-C, SIGINTdikirim. Prosesnya biasanya mati. Apa lagi yang bisa diberikan?
Ignacio Vazquez-Abrams
Kemungkinan ada deskripsi dari maksud yang harus diasumsikan pemrogram akan dimiliki pengguna ketika mereka menekan ctrl-c, misalnya semantik pesan. Sebagai contoh, spesifikasi HTTP memperjelas bahwa ketika pengguna mengirim permintaan GET, server tidak boleh berasumsi bahwa mereka ingin melakukan apa pun kecuali mengirim kembali respons.
bdsl