epoll_ctl(2)
๐ epoll_ctl โ bestie's guide to the control interface for an epoll file descriptor ๐
okay so like. this is epoll_ctl(2), from the System Calls Manual, and honestly? it's giving main character energy for anyone doing async I/O on Linux. sit down, grab a boba, we're doing this together ๐งโจ
๐ธ NAME ๐ธ
epoll_ctl โ the control interface for an epoll file descriptor. that's it, that's the vibe. it's how you tell your epoll instance what to care about ๐
๐ LIBRARY ๐
Standard C library โ <libc>, aka -lc. classic. iconic. no cap.
โจ SYNOPSIS โจ
#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd,
struct epoll_event *_Nullable event);
look at her. four args, zero drama (wellโฆ some drama, keep reading) ๐
๐ฆ DESCRIPTION ๐ฆ
so this syscall is the one that adds, modifies, or removes entries in the interest list of the epoll(7) instance that the file descriptor epfd is pointing at. you're basically saying "hey, please do op to the target file descriptor fd", and the kernel is like "say less" ๐ซถ
the valid values for the op argument are:
EPOLL_CTL_ADDโ adds an entry to the interest list of the epoll file descriptorepfd. and what goes in that entry? the file descriptorfd, a reference to the matching open file description (peepepoll(7)andopen(2)), plus all the settings you specified inevent. new friend registered โจEPOLL_CTL_MODโ changes the settings hanging out withfdin the interest list, swapping them for the new settings inevent. glow-up time ๐EPOLL_CTL_DELโ removes (deregisters) the target file descriptorfdfrom the interest list. theeventargument gets ignored and can beNULL(but see BUGS below, bestie, there's a plot twist ๐). it's not you, it's justโฆ you're not in the list anymore.
the event argument describes the object linked to the file descriptor fd. the struct epoll_event is described over in epoll_event(3type) if you wanna go deeper ๐
the data member of the epoll_event structure is where you stash data that the kernel should save, and then hand back to you (via epoll_wait(2)) when that file descriptor becomes ready. it's like leaving a lil note for future you ๐
the events member of the epoll_event structure is a bit mask, and you build it by ORing together zero or more event types (which epoll_wait(2) returns) and input flags (which change behavior but aren't returned). so, the available event types:
EPOLLINโ the associated file is available forread(2)operations. it's readable, go get it ๐ฅEPOLLOUTโ the associated file is available forwrite(2)operations. it's writable, go off ๐คEPOLLRDHUP(since Linux 2.6.17) โ stream socket peer closed the connection, or shut down the writing half of the connection. (this flag is especially useful for writing simple code that detects peer shutdown when you're doing edge-triggered monitoring. tiny but mighty ๐ง)EPOLLPRIโ there's an exceptional condition on the file descriptor. go read the discussion ofPOLLPRIinpoll(2)for the lore ๐จEPOLLERRโ an error condition happened on the associated file descriptor. this one is also reported for the write end of a pipe when the read end has been closed.epoll_wait(2)will always report for this event; you do not need to set it ineventswhen callingepoll_ctl(). it shows up whether you invited it or not ๐EPOLLHUPโ hang up happened on the associated file descriptor.epoll_wait(2)will always wait for this event; you do not need to set it ineventswhen callingepoll_ctl(). also a permanent plus-one. note that when you're reading from a channel like a pipe or a stream socket, this event merely indicates that the peer closed its end of the channel โ subsequent reads from the channel will return0(end of file) only after all the outstanding data in the channel has been consumed. so don't panic-drain, okay? ๐ญ
and the available input flags:
EPOLLETโ requests edge-triggered notification for the associated file descriptor. the default behavior for epoll is level-triggered. go seeepoll(7)for the more detailed tea on edge-triggered vs level-triggered notification ๐ตEPOLLONESHOT(since Linux 2.6.2) โ requests one-shot notification for the associated file descriptor. meaning: after one event is notified for that file descriptor byepoll_wait(2), the file descriptor is disabled in the interest list and no other events will be reported by the epoll interface. you have to callepoll_ctl()withEPOLL_CTL_MODto rearm the file descriptor with a new event mask. one and done, then you re-up ๐EPOLLWAKEUP(since Linux 3.5) โ ifEPOLLONESHOTandEPOLLETare clear and the process has theCAP_BLOCK_SUSPENDcapability, make sure the system does not enter "suspend" or "hibernate" while this event is pending or being processed. the event counts as "processed" from the moment it's returned by a call toepoll_wait(2)until the next call toepoll_wait(2)on the sameepoll(7)file descriptor, the closure of that file descriptor, the removal of the event file descriptor withEPOLL_CTL_DEL, or the clearing ofEPOLLWAKEUPfor the event file descriptor withEPOLL_CTL_MOD. see also BUGS ๐EPOLLEXCLUSIVE(since Linux 4.5) โ sets an exclusive wakeup mode for the epoll file descriptor being attached to the target file descriptorfd. when a wakeup event happens and multiple epoll file descriptors are attached to the same target file usingEPOLLEXCLUSIVE, one or more of those epoll file descriptors will receive an event withepoll_wait(2). the default in that scenario (whenEPOLLEXCLUSIVEis not set) is for all epoll file descriptors to receive an event. soEPOLLEXCLUSIVEis useful for avoiding thundering herd problems in certain scenarios. nobody likes a stampede ๐- if the same file descriptor is in multiple epoll instances, some with the
EPOLLEXCLUSIVEflag and others without, then events will be provided to all epoll instances that did not specifyEPOLLEXCLUSIVE, and to at least one of the epoll instances that did specifyEPOLLEXCLUSIVE. - these values may be specified in conjunction with
EPOLLEXCLUSIVE:EPOLLIN,EPOLLOUT,EPOLLWAKEUP, andEPOLLET.EPOLLHUPandEPOLLERRcan also be specified, but that's not required: as usual, these events are always reported if they occur, regardless of whether they're specified inevents. attempts to specify other values ineventsyield the errorEINVAL๐ซ EPOLLEXCLUSIVEmay be used only in anEPOLL_CTL_ADDoperation; attempts to use it withEPOLL_CTL_MODyield an error. ifEPOLLEXCLUSIVEhas been set usingepoll_ctl(), then a subsequentEPOLL_CTL_MODon the sameepfd,fdpair yields an error. a call toepoll_ctl()that specifiesEPOLLEXCLUSIVEineventsand specifies the target file descriptorfdas an epoll instance will likewise fail. the error in all of these cases isEINVAL. the rules are the rules, bestie ๐ค
- if the same file descriptor is in multiple epoll instances, some with the
๐ RETURN VALUE ๐
when it works: epoll_ctl() returns zero. when something goes wrong: epoll_ctl() returns -1 and errno is set to tell you what happened. classic king behavior ๐
๐ ERRORS ๐
EBADFโepfdorfdis not a valid file descriptor.EEXISTโopwasEPOLL_CTL_ADD, and the supplied file descriptorfdis already registered with this epoll instance. she's already on the guest list, babe ๐๏ธEINVALโepfdis not an epoll file descriptor, orfdis the same asepfd, or the requested operationopis not supported by this interface.EINVALโ an invalid event type was specified along withEPOLLEXCLUSIVEinevents.EINVALโopwasEPOLL_CTL_MODandeventsincludedEPOLLEXCLUSIVE.EINVALโopwasEPOLL_CTL_MODand theEPOLLEXCLUSIVEflag has previously been applied to thisepfd,fdpair.EINVALโEPOLLEXCLUSIVEwas specified ineventandfdrefers to an epoll instance.ELOOPโfdrefers to an epoll instance and thisEPOLL_CTL_ADDoperation would result in a circular loop of epoll instances monitoring one another, or a nesting depth of epoll instances greater than 5. no ouroboros energy allowed, the limit is 5, periodt ๐ENOENTโopwasEPOLL_CTL_MODorEPOLL_CTL_DEL, andfdis not registered with this epoll instance. who? never heard of her ๐ENOMEMโ there was insufficient memory to handle the requestedopcontrol operation.ENOSPCโ the limit imposed by/proc/sys/fs/epoll/max_user_watcheswas encountered while trying to register (EPOLL_CTL_ADD) a new file descriptor on an epoll instance. seeepoll(7)for further details.EPERMโ the target filefddoes not support epoll. this error can occur iffdrefers to, for example, a regular file or a directory. sorry babe, not everyone gets to play ๐ซ
๐ STANDARDS ๐
Linux. that's the whole section. Linux only, iykyk ๐ง
๐ฐ๏ธ HISTORY ๐ฐ๏ธ
Linux 2.6, glibc 2.3.2. old money โจ
๐ NOTES ๐
the epoll interface supports all file descriptors that support poll(2). equality, honestly ๐ซถ
๐ BUGS ๐
listen. before Linux 2.6.9, the EPOLL_CTL_DEL operation required a non-null pointer in event, even though that argument is ignored. since Linux 2.6.9, event can be specified as NULL when using EPOLL_CTL_DEL. so if your application needs to be portable to kernels before Linux 2.6.9, you should specify a non-null pointer in event. ancient-kernel girlies, this one's for you ๐
and second: if EPOLLWAKEUP is specified in flags, but the caller does not have the CAP_BLOCK_SUSPEND capability, then the EPOLLWAKEUP flag is silently ignored. why, you ask? because this unfortunate behavior is necessary: no validity checks were performed on the flags argument in the original implementation, and adding EPOLLWAKEUP with a check that made the call fail if the caller didn't have CAP_BLOCK_SUSPEND caused a breakage in at least one existing user-space application that happened to randomly (and uselessly) specify this bit. so yeah. a robust application should therefore double check that it has the CAP_BLOCK_SUSPEND capability if it's attempting to use the EPOLLWAKEUP flag. trust but verify, bestie ๐
๐ SEE ALSO ๐
epoll_create(2), epoll_wait(2), ioctl_eventpoll(2), poll(2), epoll(7). go read the whole friend group, they're all iconic ๐
okay that's the whole page, and for the cute sign-off: this was epoll_ctl(2) from Linux man-pages 6.20, dated 2025-12-25 ๐ happy epolling, go rearm responsibly, and remember โ if epoll_wait(2) says it's ready, it's ready. bye bestie ๐
โจ๐ฆ
๐ฆ where this page comes from
- arch rolling: man-pages 6.20-1 ยท BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- ๐ the page's license: GPL-2.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms