Prompt dan Kapan Ini Berlaku
Layanan TCP Linux mengatur listening socket dan connected socket-nya ke mode nonblocking dan menjalankannya dengan epoll. Sebuah klien telah menempatkan 8 KiB di receive buffer suatu koneksi. Setelah epoll_wait mengembalikan EPOLLIN, handler memanggil recv sekali, mengonsumsi 4 KiB, dan kembali.
Dengan mode level-triggered default, LT, epoll_wait berikutnya sering kali melaporkan koneksi tersebut lagi. Setelah mengaktifkan mode edge-triggered dengan EPOLLET, ET, implementasi yang sama terkadang tidak menerima notifikasi readable lebih lanjut dan klien menunggu selamanya. Jelaskan:
- apa arti interest list, ready list, dan kesiapan (readiness) I/O pada
epoll; - mengapa kontrak notifikasi LT dan ET menghasilkan hasil yang berbeda;
- bagaimana ET harus menangani
accept,recv,send,EAGAIN, half-close, dan error; - apa risiko tambahan yang dibawa oleh worker thread,
EPOLLONESHOT, keadilan (fairness) hot-connection, dan penggunaan kembali (reuse) FD; - cara mengonfirmasi penyebabnya dan memverifikasi perbaikannya dengan eksperimen yang dapat diulang.
Nilai 8 KiB dan 4 KiB adalah input wawancara. Itu bukan ukuran tetap untuk pengiriman TCP, system call, atau pesan aplikasi. Kompetensi intinya adalah kontrak kesiapan I/O Linux, yang berlaku untuk peran backend, infrastruktur, SRE, sistem, dan rekayasa perangkat lunak umum, sehingga kategorinya adalah general.
Apa yang Diuji oleh Pewawancara
Pertama, dapatkah kandidat menyatakan bahwa epoll melaporkan kesiapan (readiness)—apakah suatu kelas I/O dapat membuat kemajuan tanpa memblokir—bukan bahwa satu permintaan lengkap telah tiba dan bukan bahwa asynchronous I/O telah selesai? TCP adalah aliran byte (byte stream), dan satu recv dapat mengembalikan sejumlah byte positif berapa pun yang saat ini tersedia.
Kedua, apakah mereka memahami LT dan ET lebih dari sekadar slogan? LT terus melapor selama kondisi kesiapan yang diminta terpenuhi. ET tidak menjanjikan notifikasi lain hanya karena kondisinya tetap benar. Setelah peristiwa ET, aplikasi harus memperlakukan FD sebagai dapat ditindaklanjuti hingga pembacaan atau penulisan nonblocking mengembalikan EAGAIN atau EWOULDBLOCK. "ET hanya memberi tahu sekali" terlalu mutlak dan tidak menghasilkan implementasi yang benar.
Ketiga, dapatkah mereka menerapkan aturan yang sama untuk read, write, dan listening socket? Kuras (drain) pembacaan hingga EAGAIN; lakukan perulangan accept4 hingga EAGAIN; dan jangan memantau EPOLLOUT secara permanen pada socket yang biasanya dapat ditulis (writable). Pantau hanya saat aplikasi memiliki data buffer yang belum terkirim.
Keempat, dapatkah mereka mengelola status konkuren? EPOLLONESHOT menonaktifkan FD setelah satu notifikasi. Worker harus mempersenjatai kembali (rearm) dengan EPOLL_CTL_MOD setelah menyelesaikan pembaruan statusnya. Melakukan rearm terlalu dini dapat membuat dua worker menyentuh satu koneksi; lupa melakukan rearm terlihat seperti kemacetan permanen.
Kelima, dapatkah mereka menyelaraskan "kuras hingga EAGAIN" dengan keadilan (fairness) event-loop? Koneksi yang terus-menerus sibuk dapat menyita thread terlalu lama. Jika aplikasi berhenti lebih awal untuk menegakkan keadilan, aplikasi harus mempertahankan koneksi tersebut dalam antrean runnable di user-space alih-alih mengharapkan ET menciptakan edge baru.
Pertanyaan untuk Diklarifikasi Sebelum Menjawab
- Apakah socket tersebut benar-benar nonblocking? Dengan ET dan FD pemblokir (blocking), pembacaan atau penulisan berikutnya dapat memblokir thread yang bertanggung jawab atas banyak koneksi.
- Apakah kemacetan terjadi pada accept, read, atau write-back? Melewatkan pengurasan accept-loop, input yang tersisa, pembaruan
EPOLLOUT, atau rearmEPOLLONESHOTsemuanya dapat terlihat seperti koneksi yang macet. - Bagaimana protokol aplikasi membatasi pesan? TCP tidak memiliki batasan pesan. Awalan panjang (length prefix), pembatas (delimiter), status parser HTTP, atau penutupan koneksi menentukan kapan suatu permintaan selesai.
- Berapa banyak yang dibaca oleh handler, dan kapan ia kembali? Satu pembacaan tetap per event adalah bug langsung di sini; pekerjaan bisnis yang mahal di dalam loop pengurasan menciptakan masalah keadilan (fairness).
- Bisakah koneksi berpindah antar thread? Identifikasi pemilik input, output, close, dan
epoll_ctl, serta apakahEPOLLONESHOTdiaktifkan. - Apakah
EPOLLOUTselalu dilanggan (subscribed)? Socket biasanya dapat ditulis hampir sepanjang waktu. Langganan LT permanen dapat membuatepoll_waitlangsung kembali dalam loop yang membakar CPU. - Bagaimana
EPOLLRDHUP,EPOLLHUP, danEPOLLERRditangani? Data mungkin masih tersisa saat HUP tiba, dan ERR/HUP dilaporkan bahkan tanpa langganan eksplisit. - Bisakah nomor FD yang ditutup digunakan kembali dengan cepat? Memperlakukan integer FD sebagai seluruh identitas koneksi dapat membuat event atau tugas yang tertunda beroperasi pada koneksi baru.
Jawaban 30 Detik
"epoll mengelola interest list dan mengembalikan event dari ready list. Ini melaporkan kesiapan I/O, bukan pesan lengkap. LT terus melapor selama kondisinya tetap siap, jadi setelah membaca hanya 4 KiB, input yang tersisa biasanya menyebabkan wait berikutnya mengembalikan FD. ET tidak menjanjikan laporan berulang untuk kondisi siap yang tidak berubah, sehingga pembacaan parsial dapat menunggu selamanya untuk notifikasi yang tidak pernah datang.
Semua FD ET harus nonblocking. Kuras listening socket dengan accept4 hingga EAGAIN, pembacaan dengan recv hingga EAGAIN, dan penulisan dengan send hingga EAGAIN; pantau EPOLLOUT hanya saat buffer output tidak kosong. Nilai recv nol berarti penutupan tertib dari separuh penulisan (write-half close) oleh peer, sementara error lain memerlukan penanganan terpisah. Dengan banyak worker, EPOLLONESHOT dapat menserialisasi koneksi, tetapi harus dipersenjatai kembali (rearm) dengan MOD setelah pembaruan status. Anggaran keadilan (fairness budget) diperbolehkan, tetapi berhenti sebelum EAGAIN memerlukan ready queue di user-space. Saya akan mereproduksi dengan input tersegmentasi, pembacaan dan penulisan parsial, half-close, dan konkurensi, lalu membuktikan setiap koneksi mencapai EAGAIN, di-rearm dengan benar, dan tidak mengalami busy-loop."
Pembahasan Mendalam Langkah demi Langkah
Langkah 1: Tetapkan model kesiapan epoll
epoll_create1 membuat instance epoll, yang dirujuk oleh sebuah FD. Secara konseptual, instance tersebut menyimpan dua set status:
- daftar minat (interest list): FD dan event mask yang didaftarkan melalui
epoll_ctl(EPOLL_CTL_ADD/MOD/DEL); - daftar siap (ready list): entri interest-list yang saat ini memiliki event yang tersedia, dari mana
epoll_waitmengembalikan hasil.
Readable berarti operasi baca saat ini dapat memperoleh data, EOF, atau error tanpa menunggu. Writable berarti operasi tulis saat ini dapat membuat setidaknya sedikit kemajuan; ini tidak menjanjikan seluruh respons muat. Aplikasi tetap memanggil recv, send, atau accept4 dan menginterpretasikan nilai kembaliannya. Event mendorong tindakan; hasil system call menggerakkan state machine.
Langkah 2: Bandingkan LT dan ET dengan 4 KiB yang belum dibaca
LT default menyerupai poll: selama receive buffer masih menyimpan data, kesiapan baca tetap bernilai true dan epoll_wait berikutnya dapat mengembalikan FD itu lagi. Oleh karena itu, implementasi "satu baca per event" yang salah dapat tampak berfungsi, dengan konsekuensi lebih banyak wakeup dan system call.
Dengan EPOLLET, kernel melaporkan tepi/perubahan (edges) dalam kesiapan. Setelah handler mengonsumsi 4 KiB, 4 KiB lainnya tersisa dan FD masih dapat dibaca; aplikasi tidak pernah memajukannya ke "tidak ada data lagi sekarang." ET tidak menjanjikan laporan lain untuk kondisi yang tidak berubah itu, sehingga menunggu event baru dapat memblokir tanpa batas waktu.
Aturan yang andal adalah memperlakukan FD yang dikembalikan oleh ET sebagai siap dan terus melakukan I/O nonblocking hingga mengembalikan EAGAIN atau EWOULDBLOCK. Nilai-nilai tersebut berarti tidak ada operasi lebih lanjut yang saat ini dapat membuat kemajuan tanpa memblokir. Hanya setelah itu aplikasi menyerahkan kembali tanggung jawab notifikasi ke epoll.
Langkah 3: Jadikan pembacaan sebagai state machine eksplisit
Sketsa mirip C ini menghilangkan detail parser, masa pakai (lifetime), dan pencatatan log (logging) spesifik aplikasi:
void drain_read(Connection *conn) {
unsigned char buf[4096];
for (;;) {
ssize_t n = recv(conn->fd, buf, sizeof buf, 0);
if (n > 0) {
append_and_parse(conn, buf, (size_t)n);
continue;
}
if (n == 0) {
conn->peer_write_closed = true;
break;
}
if (errno == EINTR) {
continue;
}
if (errno == EAGAIN || errno == EWOULDBLOCK) {
break;
}
close_with_error(conn, errno);
return;
}
if (conn->peer_write_closed && output_is_empty(conn)) {
close_connection(conn);
}
}n > 0 hanya berarti byte-byte tersebut telah tiba; parser mungkin masih kekurangan pesan yang lengkap. n == 0 adalah penutupan teratur oleh peer pada stream socket, setelah data yang sudah di-buffer dikonsumsi. EINTR dapat dicoba lagi, EAGAIN/EWOULDBLOCK menyelesaikan pass pengurasan ini, dan error lainnya masuk ke jalur penutupan. Pembacaan pendek (short read) bukanlah bukti selesainya pesan atau kosongnya socket.
Listening socket mengikuti pola yang sama. Pada kondisi readability, lakukan loop pada accept4, secara atomik menerapkan SOCK_NONBLOCK | SOCK_CLOEXEC ke setiap koneksi baru, hingga EAGAIN. Menerima hanya satu koneksi dapat menelantarkan koneksi lain yang sudah mengantre di bawah ET tanpa jaminan notifikasi berikutnya.
Langkah 4: Kontrol buffering output dan EPOLLOUT
Cobalah untuk mengirim output yang di-buffer segera. Pada send parsial, majukan offset dan lanjutkan. Coba lagi EINTR. Pada EAGAIN/EWOULDBLOCK, pertahankan sisa byte dan tambahkan EPOLLOUT melalui EPOLL_CTL_MOD. Lanjutkan pengurasan pada event writable berikutnya. Hapus EPOLLOUT dari interest mask segera setelah buffer output kosong.
Langganan EPOLLOUT permanen menciptakan mode kegagalan yang berbeda: socket sering kali dapat ditulis untuk jangka waktu yang lama, sehingga LT berulang kali kembali seketika dan CPU meningkat tanpa adanya kemajuan bisnis. ET tidak menghilangkan buffer output aplikasi, backpressure, batas maksimum buffer, atau kebijakan slow-client; ini hanya mengubah perilaku notifikasi.
Langkah 5: Tangani half-close, HUP, ERR, dan urutan penutupan
EPOLLRDHUP menunjukkan bahwa peer stream telah menutup koneksi atau separuh penulisan miliknya. EPOLLHUP menyatakan bahwa peer menutup sisinya pada channel tersebut, tetapi data mungkin tetap belum dibaca; menutupnya segera dapat membuang data tersebut. EPOLLERR dan EPOLLHUP dilaporkan bahkan saat tidak diminta secara eksplisit. Pada ERR, getsockopt(SO_ERROR) dapat mengambil error socket yang tertunda sebelum aplikasi mencatat dan menutupnya sesuai dengan kebijakan protokol.
Jalur penutupan harus terlebih dahulu menghentikan penugasan pekerjaan baru dan memastikan tugas-tugas asynchronous tidak dapat mempertahankan identitas yang telah kedaluwarsa. Menutup FD terakhir yang merujuk pada deskripsi berkas terbuka yang mendasarinya (underlying open file description) memungkinkan kernel menghapus pendaftaran. Jika dup atau fork berbagi deskripsi tersebut, menutup satu FD tidak perlu langsung menghilangkan event terkait, sehingga protokol kepemilikan harus secara eksplisit melakukan DEL pada entri tersebut atau menutup setiap referensi. Gunakan objek koneksi dengan masa pakai terkontrol dan generasi atau token sehingga penggunaan kembali integer FD yang cepat tidak dapat mengarahkan pekerjaan lama ke koneksi baru.
Langkah 6: Gunakan EPOLLONESHOT untuk kepemilikan worker
Beberapa thread dapat menunggu pada satu instance epoll. Untuk FD ET, kernel biasanya membangunkan satu waiter saat FD siap, tetapi hal itu saja tidak membuat koneksi berpemilik tunggal di sepanjang pemrosesan. Pekerjaan yang diantrekan dan event selanjutnya masih dapat menciptakan akses bersamaan (concurrent access).
EPOLLONESHOT menonaktifkan FD setelah satu pengiriman event. Setelah menguras I/O dan memperbarui status protokol serta interest mask, worker yang menjaga koneksi tetap hidup memanggil epoll_ctl(EPOLL_CTL_MOD) untuk mempersenjatai kembali (rearm). Rearm harus menjadi langkah serah terima terakhir. Lupa melakukan MOD akan menghentikan koneksi; melakukannya terlalu dini dapat membiarkan worker baru masuk sebelum pemilik lama selesai.
Langkah 7: Pertahankan kebenaran ET dan keadilan (fairness) secara bersamaan
Menguras hingga EAGAIN dapat membiarkan koneksi yang terus-menerus sibuk menguasai thread dan menunda koneksi lain. Loop dapat memberlakukan anggaran byte, pesan, atau waktu per koneksi. Jika anggaran tersebut habis sebelum EAGAIN, ia tidak dapat sekadar kembali dan menunggu kernel. Ia harus menandai koneksi sebagai runnable dalam ready queue di user-space dan melanjutkannya nanti hingga mencapai EAGAIN.
Antrean harus mencegah entri duplikat. Penutupan koneksi, transfer worker, dan rearm EPOLLONESHOT harus berbagi protokol kepemilikan yang sama. Ini menjaga kontrak ET tanpa membiarkan satu FD yang sibuk membuat FD lainnya kelaparan (starve).
Langkah 8: Bangun verifikasi yang mengungkap edge yang hilang
Satu permintaan normal saja tidak cukup. Cakup setidaknya:
- satu penulisan klien 8 KiB sementara server sengaja membaca paling banyak 4 KiB per panggilan, menunjukkan kemacetan ET sebelum perbaikan dan pengurasan hingga
EAGAINsetelah perbaikan; - satu pesan aplikasi yang dibagi menjadi beberapa pengiriman dengan jeda pada batas arbitrer, membuktikan parsing tidak bergantung pada satu ukuran
recv; - pengiriman server yang dibatasi yang menciptakan penulisan parsial dan
EAGAIN, membuktikan tidak ada byte yang hilang danEPOLLOUTdihapus setelah pengurasan; - half-close peer, HUP dengan data yang belum dibaca, connection reset, dan
EINTR; - pengiriman
EPOLLONESHOTberulang dengan beberapa worker, membuktikan tepat satu pemilik dan satu rearm untuk setiap koneksi yang hidup; - satu koneksi sibuk yang mengirim terus-menerus ditambah banyak koneksi lambat, mengamati keadilan, CPU, penundaan event-loop, dan panjang ready-queue;
- pembuatan dan penutupan koneksi yang cepat, membuktikan pekerjaan yang tertunda tidak dapat menargetkan nomor FD yang digunakan kembali.
Amati alasan terminal untuk setiap pass recv/send/accept4, jumlah EAGAIN, perubahan interest-mask, oneshot rearm, antrean siap aplikasi, anggaran per koneksi, penundaan event-loop, dan koneksi yang tidak membuat kemajuan. Lolos verifikasi berarti byte dan status protokol yang benar, tidak ada kemacetan permanen, tidak ada busy-loop kosong, tidak ada pemilik bersamaan, dan tidak ada kelaparan berkepanjangan pada koneksi lambat.
Contoh Jawaban yang Kuat
"Instance epoll mempertahankan interest list, dan epoll_wait mengembalikan event dari ready list-nya. Ini memasok kesiapan I/O, bukan pesan TCP lengkap atau penyelesaian asynchronous. Nilai kembalian system call menggerakkan state machine koneksi.
LT tampaknya pulih di sini karena setelah mengonsumsi 4 KiB, 4 KiB lainnya tersisa, sehingga kesiapan baca masih berlaku dan wait berikutnya melaporkan FD lagi. Dengan EPOLLET, FD tidak pernah kembali ke status non-readable. ET tidak menjanjikan notifikasi berulang untuk kondisi yang tetap bernilai true, jadi menunggu setelah satu pembacaan dapat macet selamanya.
Saya akan membuat listening socket dan connected socket menjadi nonblocking. Jalur accept melakukan loop accept4 hingga EAGAIN. Jalur read melakukan loop recv hingga EAGAIN, mengirimkan byte positif ke parser inkremental, memperlakukan nol sebagai peer write-half close, mencoba ulang EINTR, dan menutup pada error lainnya. Output mencoba send segera dan mempertahankan offset setelah penulisan parsial. Ini memantau EPOLLOUT hanya setelah EAGAIN dengan data yang masih tertunda dan menghapusnya setelah pengurasan. HUP dikuras sebelum ditutup, dan ERR didiagnosis dengan SO_ERROR.
Dengan beberapa worker, saya menetapkan satu pemilik per koneksi dan dapat menggunakan EPOLLONESHOT: worker melakukan rearm dengan MOD hanya setelah pengurasan I/O, pembaruan status, dan kalkulasi mask. Jika anggaran keadilan menghentikan pekerjaan sebelum EAGAIN, saya memasukkan koneksi ke dalam user-space ready queue yang telah dide-duplikasi alih-alih menunggu edge yang tidak ada. Identitas koneksi membawa status masa pakai atau generasi untuk bertahan dari penggunaan kembali FD dengan aman.
Saya akan mereproduksi dengan batas penulisan 8 KiB dan pembacaan 4 KiB, lalu menambahkan penulisan parsial, half-close, reset, oneshot, banyak worker, dan beban hot-connection. Perbaikan lolos jika setiap pass penanganan ET mencapai EAGAIN atau penutupan eksplisit, semua output terkirim, EPOLLOUT tidak berputar tanpa henti, setiap koneksi oneshot yang hidup di-rearm, dan tidak ada koneksi yang menganggur permanen atau kelaparan."
Kesalahan Umum
- Memperlakukan kesiapan sebagai pesan lengkap → TCP adalah byte stream, dan satu
recvbukanlah pesan aplikasi → gunakan parsing inkremental dan buffer input terpisah. - Mereduksi ET menjadi "ia selalu memberi tahu sekali" → beberapa perubahan dapat menghasilkan beberapa event; jaminan yang hilang adalah pengulangan untuk kondisi siap yang tidak berubah → proses hingga
EAGAIN. - Membaca sekali di bawah ET → input yang di-buffer tetap ada tanpa edge baru → lakukan perulangan
recvhinggaEAGAIN/EWOULDBLOCK. - Menggabungkan ET dengan socket pemblokir (blocking) → loop pengurasan dapat memblokir dan membuat seluruh event loop kelaparan → atur mode nonblocking sebelum pendaftaran.
- Menerima satu koneksi per event listener → koneksi yang sudah mengantre mungkin tidak menerima notifikasi berikutnya → lakukan perulangan
accept4hinggaEAGAIN. - Selalu melanggan
EPOLLOUT→ socket yang biasanya dapat ditulis membuat wait terus kembali seketika → langgan hanya jika ada output yang tertunda dan hapus setelah pengurasan. - Menutup segera pada HUP → data yang belum dibaca mungkin masih ada → kuras melalui read state machine, lalu tutup sesuai dengan EOF dan status output.
- Lupa melakukan rearm pada
EPOLLONESHOT→ FD tetap dinonaktifkan di interest list → gunakanEPOLL_CTL_MODsetelah pembaruan status. - Berhenti demi keadilan dan menunggu event ET lain → FD mungkin tetap siap tanpa edge baru → lanjutkan dari ready queue di user-space.
- Hanya menggunakan integer FD sebagai identitas → koneksi baru dapat menggunakan kembali nomor tersebut setelah ditutup → gunakan masa pakai terkontrol dan identitas yang membawa informasi generasi.
- Mengklaim bahwa ET secara inheren lebih cepat → hasil bergantung pada rasio aktif, system call, kerja aplikasi, dan kebenaran implementasi → ukur CPU, latensi, throughput, dan keadilan di bawah beban yang representatif.
Pertanyaan Lanjutan dan Cara Menjawabnya
Pertanyaan Lanjutan 1: Mengapa recv pendek tidak membuktikan bahwa socket telah terkuras?
recv biasanya mengembalikan apa pun yang saat ini tersedia hingga panjang yang diminta. Segmentasi jaringan, penjadwalan, dan waktu pengiriman semuanya dapat menghasilkan short read sementara lebih banyak byte tiba nanti. Batas pengurasan ET adalah EAGAIN/EWOULDBLOCK nonblocking; batas pesan aplikasi berasal dari parser protokol. Keduanya adalah batasan yang berbeda.
Pertanyaan Lanjutan 2: Apakah ET selalu lebih cepat daripada LT?
Mode saja tidak dapat menjawab hal itu. ET dapat mengurangi notifikasi berulang untuk FD yang terus-menerus siap, tetapi menambah kompleksitas pengurasan, antrean di user-space, dan manajemen status. Ketika sebagian besar koneksi tidak aktif, pekerjaan aplikasi mendominasi, atau implementasi menambahkan banyak panggilan epoll_ctl, peningkatannya mungkin kecil. Ukur CPU, system call, throughput, p99, dan keadilan pada jumlah koneksi target dan distribusi aktivitas, dengan memprioritaskan kebenaran logika terlebih dahulu.
Pertanyaan Lanjutan 3: Mengapa menghapus EPOLLOUT setelah buffer output terkuras?
Writable biasanya berarti send buffer kernel dapat menerima setidaknya beberapa byte, kondisi yang tetap bernilai true untuk banyak koneksi. Memantaunya tanpa adanya output aplikasi yang tertunda menghasilkan notifikasi yang tidak berguna dan dapat menciptakan busy-loop pada LT. Pantau penulisan hanya saat byte masih tersisa; ketika output aplikasi baru muncul nanti, coba send segera sebelum berlangganan lagi.
Pertanyaan Lanjutan 4: Apakah EPOLLONESHOT dan ET adalah fitur yang sama?
Tidak. EPOLLET mengubah perilaku notifikasi kesiapan. EPOLLONESHOT menonaktifkan FD setelah satu pengiriman event sampai aplikasi melakukan rearm dengan EPOLL_CTL_MOD. Keduanya dapat digabungkan. ONESHOT membantu mentransfer kepemilikan worker, tetapi ET tetap memerlukan pengurasan yang benar dan aplikasi tetap memerlukan protokol rearm.
Pertanyaan Lanjutan 5: Anggaran keadilan habis sebelum EAGAIN; bagaimana cara menghindari hilangnya event?
Tandai koneksi sebagai masih runnable di user-space dan tempatkan dalam ready queue yang telah dide-duplikasi. Penjadwal melanjutkan recv/send hingga EAGAIN, penutupan, atau kedaluwarsa anggaran lainnya. Pertahankan pemilik yang valid saat mengantre. Dengan ONESHOT, lakukan rearm hanya setelah pekerjaan di user-space selesai dan koneksi memerlukan notifikasi kernel lagi.
Pertanyaan Lanjutan 6: Mengapa perlu mengkhawatirkan event lama setelah menutup FD?
Kumpulan event (batch) mungkin sudah berada di user-space, dan asynchronous worker dapat mempertahankan referensi koneksi sementara kernel dengan cepat menetapkan integer yang sama ke socket baru. Beberapa FD juga dapat merujuk pada satu deskripsi file terbuka yang sama. Jalur penutupan harus menghentikan dispatch baru, mengelola masa pakai objek, dan membatalkan token lama. Membandingkan integer FD saja tidak dapat membuktikan bahwa suatu event milik koneksi saat ini.