Ada jawaban yang bagus pada StackOverflow tentang memberikan kunci yang lebih baik untuk daemon (disintesis dari Eduardo Fleury ) yang tidak bergantung pada mekanisme kunci file PID umum untuk daemon. Ada banyak komentar bagus di sana tentang mengapa file kunci PID terkadang dapat menyebabkan masalah, jadi saya tidak akan mengulanginya di sini.
Singkatnya, solusinya bergantung pada soket domain namespace abstrak Linux, yang melacak soket berdasarkan nama untuk Anda, daripada mengandalkan file, yang dapat bertahan setelah daemon SIGKILL'd. Contoh tersebut menunjukkan bahwa Linux tampaknya membebaskan soket setelah proses mati.
Tapi saya tidak dapat menemukan dokumentasi definitif di Linux yang mengatakan apa yang sebenarnya Linux lakukan dengan soket abstrak ketika proses terikat SIGKILL. Apakah ada yang tahu?
Dengan kata lain, kapan tepatnya soket abstrak dibebaskan untuk digunakan lagi?
Saya tidak ingin mengganti mekanisme file PID dengan soket abstrak kecuali jika secara definitif menyelesaikan masalah.
sumber
Jawaban:
Ya, linux secara otomatis "membersihkan" soket abstrak sejauh pembersihan bahkan masuk akal. Berikut ini contoh kerja minimal yang dapat Anda verifikasi ini:
Jalankan program ini sebagai
./a.out /test-socket &
, lalu jalankanss -ax | grep test-socket
, dan Anda akan melihat soket yang digunakan. Kemudiankill %./a.out
, danss -ax
akan ditampilkan soket yang hilang.Namun, alasan Anda tidak dapat menemukan pembersihan ini dalam dokumentasi apa pun adalah karena itu tidak benar-benar membersihkan dalam arti yang sama bahwa soket unix-domain non-abstrak perlu dibersihkan. Soket non-abstrak sebenarnya mengalokasikan inode dan membuat entri dalam direktori, yang perlu dibersihkan di sistem file yang mendasarinya. Sebaliknya, pikirkan soket abstrak yang lebih mirip nomor port TCP atau UDP. Tentu, jika Anda mengikat port TCP dan kemudian keluar, port TCP itu akan bebas lagi. Tetapi berapa pun angka 16-bit yang Anda gunakan masih ada secara abstrak dan selalu dilakukan. Namespace nomor port adalah 1-65535 dan tidak pernah berubah atau perlu dibersihkan.
Jadi pikirkan saja nama soket abstrak seperti nomor port TCP atau UDP, baru saja memilih dari sekumpulan nomor port yang jauh lebih besar yang kebetulan terlihat seperti nama path tetapi tidak. Anda tidak dapat mengikat nomor port yang sama dua kali (kecuali
SO_REUSEADDR
atauSO_REUSEPORT
). Tetapi menutup soket (secara eksplisit atau implisit dengan mengakhiri) membebaskan port, tanpa ada yang tersisa untuk dibersihkan.sumber
Saya memposting pertanyaan ini lebih dari setahun yang lalu dan tidak pernah cukup puas dengan kurangnya dokumentasi yang pasti. Saya pikir saya akan memeriksa dokumentasi Linux lagi untuk setiap pembaruan, dan senang melihat ini :
Juga, Antarmuka Pemrograman Linux oleh Michael Kerrisk mencakup pertanyaan (dikirim silang dari jawaban lain ini ):
Saya rasa itu, bersama dengan jawaban @ user3188445, ini membersihkan pertanyaan dengan sangat tepat.
Yang mengatakan, masih ada asumsi yang dibuat di sini, bahwa proses yang SIGKILL akan menutup semua soket terbuka. Itu tampaknya asumsi yang masuk akal, tetapi saya tidak memiliki dokumentasi yang mendefinisikan perilaku itu.
sumber
SOCK_CLOEXEC
jika seandainya ada kode (termasuk perpustakaan) yang pernah melakukan fork () + exec (). Membuat proses anak tambahan menggunakan fork () tanpa exec () kurang umum; Anda mungkin sudah tahu jika Anda melakukan itu.