Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file epoll_file_descr_watcher.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173openCoreopenImportopenFile_descr_watcher_intfopenRead_write_pair.ExportmoduleEpoll=Linux_ext.EpollmoduleTimerfd=Linux_ext.TimerfdmoduleFlags=structincludeEpoll.Flagsletin_out=in_+out(* Use the edge-triggered behavior so we don't have to reset the timerfd when it
expires. *)letfor_timerfd=in_+etletof_rw=function|`Read->in_|`Write->out;;endtypet={timerfd:Timerfd.t;epoll:Epoll.t;handle_fd_read_ready:File_descr.t->Flags.t->unit;handle_fd_write_ready:File_descr.t->Flags.t->unit}[@@derivingsexp_of,fields]letbackend=Config.File_descr_watcher.Epollletis_timerfdtfd=File_descr.equalfd(Timerfd.to_file_descrt.timerfd)letinvariantt:unit=tryletcheckffield=f(Field.getfieldt)inFields.iter~timerfd:(check(funtimerfd->[%test_result:Flags.toption](Epoll.findt.epoll(Timerfd.to_file_descrtimerfd))~expect:(SomeFlags.for_timerfd)))~epoll:(check(funepoll->Epoll.iterepoll~f:(fun_flags->assert(List.existsFlags.[in_;out;in_out;for_timerfd]~f:(funflags'->Flags.equalflagsflags')))))~handle_fd_read_ready:ignore~handle_fd_write_ready:ignorewith|exn->raise_s[%message"Epoll_file_descr_watcher.invariant failed"(exn:exn)~epoll_file_descr_watcher:(t:t)];;type'aadditional_create_args=timerfd:Linux_ext.Timerfd.t->'aletcreate~timerfd~num_file_descrs~handle_fd_read_ready~handle_fd_write_ready=letepoll=Or_error.ok_exnEpoll.create~num_file_descrs~max_ready_events:(Epoll_max_ready_events.rawConfig.epoll_max_ready_events)inleterr_or_hup=Flags.(hup+err)inlethandle_fdread_or_writehandle_fd=letbit=Flags.of_rwread_or_writeinfunfile_descrflags->(* A difference between select and epoll crops up here: epoll has implicit event
flags for hangup (HUP) and error (ERR), whereas select will just return that fd
as "ready" in its appropriate fd_set. Since we don't know if it's ready for IN
or OUT, we have to go lookup the entry if the HUP or ERR flag is set. *)ifFlags.do_intersectflagsbit||(Flags.do_intersectflagserr_or_hup&&Flags.do_intersect(Epoll.find_exnepollfile_descr)bit)thenhandle_fdfile_descrinEpoll.setepoll(Timerfd.to_file_descrtimerfd)Flags.for_timerfd;{timerfd;epoll;handle_fd_read_ready=handle_fd`Readhandle_fd_read_ready;handle_fd_write_ready=handle_fd`Writehandle_fd_write_ready};;letreset_in_forked_processt=Epoll.closet.epollletitert~f=Epoll.itert.epoll~f:(funfile_descrflags->ifnot(is_timerfdtfile_descr)then(ifFlags.do_intersectflagsFlags.in_thenffile_descr`Read;ifFlags.do_intersectflagsFlags.outthenffile_descr`Write));;letsettfile_descrdesired=letactual_flags=Epoll.findt.epollfile_descrinletdesired_flags=matchdesired.read,desired.writewith|false,false->None|true,false->SomeFlags.in_|false,true->SomeFlags.out|true,true->SomeFlags.in_outinmatchactual_flags,desired_flagswith|None,None->`Ok|None,Somed->(matchEpoll.sett.epollfile_descrdwith|exceptionCore_unix.Unix_error(EPERM,_,_)->`Unsupported|()->`Ok)|Some_,None->Epoll.removet.epollfile_descr;`Ok|Somea,Somed->ifnot(Flags.equalad)thenEpoll.sett.epollfile_descrd;`Ok;;modulePre=structtypet=unit[@@derivingsexp_of]endletpre_check_t=()moduleCheck_result=structtypet=([`Ok|`Timeout],exn*Backtrace.t)Result.t[@@derivingsexp_of]letok=Ok`Oklettimeout=Ok`Timeoutendletepoll_wait(typea)(epoll:Epoll.t)(timeout:aTimeout.t)(span_or_unit:a)=matchtimeoutwith|Immediately->Epoll.waitepoll~timeout:`Immediately|After->Epoll.wait_timeout_afterepollspan_or_unit;;letthread_safe_checkt()timeoutspan_or_unit=matchepoll_waitt.epolltimeoutspan_or_unitwith|`Ok->Check_result.ok|`Timeout->Check_result.timeout|exceptione->Error(e,Backtrace.Exn.most_recent());;letpost_checktcheck_result=trymatchcheck_resultwith(* We think 514 should be treated like EINTR. *)|Error(Unix.Unix_error((EINTR|EUNKNOWNERR514),_,_),_)->()|Error(exn,backtrace)->raise_s[%message"epoll raised unexpected exn"(exn:exn)(backtrace:Backtrace.t)]|Ok`Timeout->()|Ok`Ok->Epoll.iter_readyt.epoll~f:t.handle_fd_write_ready;Epoll.iter_readyt.epoll~f:t.handle_fd_read_ready;Epoll.Expert.clear_readyt.epollwith|exn->letbacktrace=Backtrace.Exn.most_recent()inraise_s[%message"Epoll.post_check bug"(exn:exn)(backtrace:Backtrace.t)(check_result:Check_result.t)~epoll_file_descr_watcher:(t:t)];;