Bisakah sinyal diabaikan (hilang)?

9

Saya memiliki aplikasi yang berkomunikasi dengan para pekerja melalui sinyal (khususnya SIGUSR1 / SIGUSR2 / SIGSTOP).

Dapatkah saya percaya bahwa apa pun yang terjadi setiap sinyal akan dikirimkan dan diproses oleh handler?

Apa yang terjadi jika sinyal dikirim lebih cepat daripada yang tidak mungkin bagi aplikasi untuk menanganinya (mis. Karena beban host yang tinggi saat ini)?

KaP
sumber

Jawaban:

8

Selain masalah "terlalu banyak sinyal", sinyal dapat diabaikan secara eksplisit. Dari man 2 signal:

If the signal signum is delivered to the process, then one of the
following happens:    
  *  If the disposition is set to SIG_IGN, then the signal is ignored.

Sinyal juga dapat diblokir. Dari man 7 signal;

A signal may be blocked, which means that it will not be delivered
until it is later unblocked.  Between the time when it is generated
and when it is delivered a signal is said to be pending.

Kedua set sinyal yang diblokir dan diabaikan diwarisi oleh proses anak, sehingga dapat terjadi bahwa proses induk aplikasi Anda mengabaikan atau memblokir salah satu sinyal ini.

Apa yang terjadi ketika beberapa sinyal dikirim sebelum proses selesai menangani yang sebelumnya? Itu tergantung pada OS. Halaman yang signal(2)terhubung di atas membahasnya:

  • Sistem V akan mengatur ulang disposisi sinyal ke default. Lebih buruk lagi, pengiriman cepat dari beberapa sinyal akan menghasilkan panggilan rekursif (?).
  • BSD akan secara otomatis memblokir sinyal sampai pawang selesai.
  • Di Linux, ini tergantung pada flag kompilasi yang diatur untuk GNU libc, tapi saya mengharapkan perilaku BSD.
muru
sumber
4
Halaman manual Linux dengan signal(2)tegas menyarankan agar Anda menghindari kebingungan ini dengan menggunakannya sigaction(2).
Nate Eldredge
7

Anda tidak dapat mempercayai bahwa setiap sinyal yang dikirim akan dikirimkan. Sebagai contoh, kernel linux "menyatukan" SIGCHLD jika suatu proses membutuhkan waktu lama dalam menangani SIGCHLD dari proses anak yang sudah keluar.

Untuk menjawab bagian lain dari pertanyaan Anda, sinyal "antri" di dalam kernel jika sejumlah sinyal berbeda datang terlalu pendek.

Anda harus menggunakan sigaction()untuk mengatur pengendali sinyal dengan sa_sigactionanggota siginfo_t, mengatur sa_maskanggota siginfo_targumen dengan hati-hati. Saya pikir ini berarti menutupi semua sinyal "asynch" setidaknya. Menurut halaman manual untuk Linux sigaction(), Anda juga akan menutupi sinyal yang sedang ditangani. Saya pikir Anda harus mengatur sa_flagsanggota untuk SA_SIGINFO, tetapi saya tidak ingat mengapa saya memiliki takhayul ini. Saya percaya ini akan membuat proses Anda penangan sinyal yang tetap diatur tanpa kondisi balapan, dan yang tidak terganggu oleh sebagian besar sinyal lainnya.

Tulis fungsi penangan sinyal Anda dengan sangat, sangat hati-hati. Pada dasarnya hanya mengatur variabel global untuk menunjukkan bahwa sinyal tertangkap, dan memiliki sisa proses berurusan dengan tindakan yang diinginkan untuk sinyal itu. Sinyal akan ditutup untuk paling sedikit waktu seperti itu.

Selain itu, Anda harus menguji kode penanganan sinyal dengan sangat teliti. Masukkan ke dalam proses pengujian kecil dan kirim sebanyak mungkin sinyal SIGUSR1 dan SIGUSR2, mungkin dari 2 atau 3 program pengiriman sinyal tujuan khusus. Campurkan beberapa sinyal lain juga, setelah Anda yakin bahwa kode Anda dapat menangani SIGUSR1 dan SIGUSR2 dengan cepat dan benar. Persiapkan diri Anda untuk debugging yang sulit.

Jika Anda menggunakan linux dan hanya linux, Anda mungkin berpikir untuk menggunakan signalfd()untuk membuat deskriptor file yang Anda bisa select()atau polling untuk menerima sinyal-sinyal itu. Menggunakan signalfd()mungkin membuat proses debug lebih mudah.

Bruce Ediger
sumber
2
Bukan hanya SIGCLD yang digabungkan: semua sinyal berpotensi digabungkan jika dikirim sebelum dapat diproses.
Gilles 'SO- stop being evil'
Apakah ada ukuran berapa lama "terlalu lama" untuk sinyal SIGCHLD? Saya mengalami perilaku ini dalam program saya sekarang, dan penangan sinyal saya tidak mengambil lebih dari ~ 100 ms saya akan memperhitungkan.
xrisk
@ Rishav - setahu saya tidak ada cara untuk mengetahui apa "terlalu lama" itu. Saya berharap bahwa keseluruhan beban sistem penting. Artinya, apa yang dilakukan proses lain dan kernel akan memengaruhi "berapa lama" di antara sinyal untuk bergabung. Bukan jawaban yang membantu, saya pikir.
Bruce Ediger
6

Sinyal dijamin akan dikirimkan, dalam arti jika suatu proses berhasil memanggil kill, maka target akan menerima sinyal. Ini asinkron: pengirim tidak memiliki cara untuk mengetahui kapan sinyal diterima atau diproses. Namun, ini tidak menjamin bahwa sinyal akan dikirimkan. Target bisa mati sebelum dapat memproses sinyal. Jika target mengabaikan sinyal pada saat itu disampaikan, sinyal tidak akan berpengaruh. Jika target menerima beberapa instance dari nomor sinyal yang sama sebelum dapat memprosesnya, sinyal dapat (dan biasanya) digabung: jika Anda mengirim sinyal yang sama dua kali ke suatu proses, Anda tidak dapat mengetahui apakah proses akan menerima sinyal sekali atau dua kali. Sinyal sebagian besar dirancang untuk mematikan proses atau sebagai cara untuk membuat proses memperhatikan, mereka tidak dirancang untuk komunikasi seperti itu.

Jika Anda membutuhkan pengiriman yang andal maka Anda memerlukan mekanisme komunikasi yang berbeda. Ada dua mekanisme komunikasi utama antara proses: pipa memungkinkan komunikasi searah; sebuah soket memungkinkan komunikasi dua arah dan beberapa sambungan ke server yang sama. Jika Anda memerlukan target untuk memproses sebanyak mungkin notifikasi yang Anda kirim, kirim byte melalui pipa.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
4
Apakah Anda bermaksud menulis "Sebuah sinyal dijamin akan dikirimkan" karena Anda melanjutkan dengan menjelaskan beberapa cara di mana sinyal tidak akan dikirimkan (yaitu proses mati sebelum diterima, atau sinyal digabungkan)?
Johnny
2

Kernel bebas untuk menyatukan sinyal standar jika lebih dari satu dikirimkan saat diblokir. Sinyal real-time tidak cacat sama.

Dari halaman manual signal (7) :

Sinyal waktu nyata dibedakan oleh yang berikut:

  1. Beberapa contoh sinyal waktu nyata dapat diantrekan. Sebaliknya, jika beberapa instance dari sinyal standar dikirimkan saat sinyal tersebut diblokir, maka hanya satu instance yang di-antri.

Coba gunakan sinyal dengan angka dalam rentang SIGRTMIN ke SIGRTMAX.

Graham Rushton
sumber
Ada batasan untuk sinyal real-time, tetapi cukup tinggi. Sinyal akan turun jika jumlah sinyal tertunda beredar yang dikirim oleh pengguna melebihi RLIMIT_SIGPENDING. ulimit -imenunjukkan nilai ini sebagai 63432 di Ubuntu 18,04.
bain