12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591# 1 "src/unix/lwt_unix.cppo.ml"(* This file is part of Lwt, released under the MIT license. See LICENSE.md for
details, or visit https://github.com/ocsigen/lwt/blob/master/LICENSE.md. *)(* [Lwt_sequence] is deprecated – we don't want users outside Lwt using it.
However, it is still used internally by Lwt. So, briefly disable warning 3
("deprecated"), and create a local, non-deprecated alias for
[Lwt_sequence] that can be referred to by the rest of the code in this
module without triggering any more warnings. *)[@@@ocaml.warning"-3"]moduleLwt_sequence=Lwt_sequence[@@@ocaml.warning"+3"]openLwt.Infix(* +-----------------------------------------------------------------+
| Configuration |
+-----------------------------------------------------------------+ *)typeasync_method=|Async_none|Async_detach|Async_switchletdefault_async_method_var=refAsync_detachlet()=trymatchSys.getenv"LWT_ASYNC_METHOD"with|"none"->default_async_method_var:=Async_none|"detach"->default_async_method_var:=Async_detach|"switch"->default_async_method_var:=Async_switch|str->Printf.eprintf"%s: invalid lwt async method: '%s', must be 'none', 'detach' or 'switch'\n%!"(Filename.basenameSys.executable_name)strwithNot_found->()letdefault_async_method()=!default_async_method_varletset_default_async_methodam=default_async_method_var:=amletasync_method_key=Lwt.new_key()letasync_method()=matchLwt.getasync_method_keywith|Someam->am|None->!default_async_method_varletwith_async_nonef=Lwt.with_valueasync_method_key(SomeAsync_none)fletwith_async_detachf=Lwt.with_valueasync_method_key(SomeAsync_detach)fletwith_async_switchf=Lwt.with_valueasync_method_key(SomeAsync_switch)f(* +-----------------------------------------------------------------+
| Notifications management |
+-----------------------------------------------------------------+ *)(* Informations about a notifier *)typenotifier={notify_handler:unit->unit;(* The callback *)notify_once:bool;(* Whether to remove the notifier after the reception of the first
notification *)}moduleNotifiers=Hashtbl.Make(structtypet=intletequal(x:int)(y:int)=x=ylethash(x:int)=xend)letnotifiers=Notifiers.create1024(* See https://github.com/ocsigen/lwt/issues/277 and
https://github.com/ocsigen/lwt/pull/278. *)letcurrent_notification_id=ref(0x7FFFFFFF-1000)letrecfind_free_idid=ifNotifiers.memnotifiersidthenfind_free_id(id+1)elseidletmake_notification?(once=false)f=letid=find_free_id(!current_notification_id+1)incurrent_notification_id:=id;Notifiers.addnotifiersid{notify_once=once;notify_handler=f};idletstop_notificationid=Notifiers.removenotifiersidletset_notificationidf=letnotifier=Notifiers.findnotifiersidinNotifiers.replacenotifiersid{notifierwithnotify_handler=f}letcall_notificationid=matchNotifiers.findnotifiersidwith|exceptionNot_found->()|notifier->ifnotifier.notify_oncethenstop_notificationid;notifier.notify_handler()(* +-----------------------------------------------------------------+
| Sleepers |
+-----------------------------------------------------------------+ *)letsleepdelay=letwaiter,wakener=Lwt.task()inletev=Lwt_engine.on_timerdelayfalse(funev->Lwt_engine.stop_eventev;Lwt.wakeupwakener())inLwt.on_cancelwaiter(fun()->Lwt_engine.stop_eventev);waiterletyield=Lwt.pauseletauto_yieldtimeout=letlimit=ref(Unix.gettimeofday()+.timeout)infun()->letcurrent=Unix.gettimeofday()inifcurrent>=!limitthenbeginlimit:=current+.timeout;yield();endelseLwt.return_unitletauto_pausetimeout=letlimit=ref(Unix.gettimeofday()+.timeout)infun()->letcurrent=Unix.gettimeofday()inifcurrent>=!limitthenbeginlimit:=current+.timeout;Lwt.pause();endelseLwt.return_unitexceptionTimeoutlettimeoutd=sleepd>>=fun()->raiseTimeoutletwith_timeoutdf=Lwt.pick[timeoutd;Lwt.applyf()](* +-----------------------------------------------------------------+
| Jobs |
+-----------------------------------------------------------------+ *)type'ajobexternalstart_job:'ajob->async_method->bool="lwt_unix_start_job"(* Starts the given job with given parameters. It returns [true]
if the job is already terminated. *)[@@@ocaml.warning"-3"]externalcheck_job:'ajob->int->bool="lwt_unix_check_job""noalloc"(* Check whether that a job has terminated or not. If it has not
yet terminated, it is marked so it will send a notification
when it finishes. *)[@@@ocaml.warning"+3"](* For all running job, a waiter and a function to abort it. *)letjobs=Lwt_sequence.create()letrecabort_jobsexn=matchLwt_sequence.take_opt_ljobswith|Some(_,f)->fexn;abort_jobsexn|None->()letcancel_jobs()=abort_jobsLwt.Canceledletwait_for_jobs()=Lwt.join(Lwt_sequence.fold_l(fun(w,_)l->w::l)jobs[])letwrap_resultfx=tryResult.Ok(fx)withexnwhenLwt.Exception_filter.runexn->Result.Errorexnletrun_job_auxasync_methodjobresult=(* Starts the job. *)ifstart_jobjobasync_methodthen(* The job has already terminated, read and return the result
immediately. *)Lwt.of_result(resultjob)elsebegin(* Thread for the job. *)letwaiter,wakener=Lwt.wait()in(* Add the job to the sequence of all jobs. *)letnode=Lwt_sequence.add_l((waiter>>=fun_->Lwt.return_unit),(funexn->ifLwt.statewaiter=Lwt.SleepthenLwt.wakeup_exnwakenerexn))jobsinignorebegin(* Create the notification for asynchronous wakeup. *)letid=make_notification~once:true(fun()->Lwt_sequence.removenode;letresult=resultjobinifLwt.statewaiter=Lwt.SleepthenLwt.wakeup_resultwakenerresult)in(* Give the job some time before we fallback to asynchronous
notification. *)Lwt.pause()>>=fun()->(* The job has terminated, send the result immediately. *)ifcheck_jobjobidthencall_notificationid;Lwt.return_unitend;waiterendletchoose_async_method=function|Someasync_method->async_method|None->matchLwt.getasync_method_keywith|Someam->am|None->!default_async_method_var[@@@ocaml.warning"-16"]letexecute_job?async_method~job~result~free=letasync_method=choose_async_methodasync_methodinrun_job_auxasync_methodjob(funjob->letx=wrap_resultresultjobinfreejob;x)[@@@ocaml.warning"+16"]externalself_result:'ajob->'a="lwt_unix_self_result"(* returns the result of a job using the [result] field of the C
job structure. *)externalrun_job_sync:'ajob->'a="lwt_unix_run_job_sync"(* Exeuctes a job synchronously and returns its result. *)letself_resultjob=tryResult.Ok(self_resultjob)withexnwhenLwt.Exception_filter.runexn->Result.Errorexnletin_retention_test=reffalseletretainedo=letretained=reftrueinGc.finalise(fun_->if!in_retention_testthenretained:=false)o;in_retention_test:=true;retainedletrun_job?async_methodjob=if!in_retention_testthenbeginGc.full_major();in_retention_test:=falseend;letasync_method=choose_async_methodasync_methodinifasync_method=Async_nonethentryLwt.return(run_job_syncjob)withexnwhenLwt.Exception_filter.runexn->Lwt.failexnelserun_job_auxasync_methodjobself_result(* +-----------------------------------------------------------------+
| File descriptor wrappers |
+-----------------------------------------------------------------+ *)typestate=Opened|Closed|Abortedofexntypefile_descr={fd:Unix.file_descr;(* The underlying unix file descriptor *)mutablestate:state;(* The state of the file descriptor *)mutableset_flags:bool;(* Whether to set file flags *)mutableblocking:boolLwt.tLazy.t;(* Is the file descriptor in blocking or non-blocking mode *)mutableevent_readable:Lwt_engine.eventoption;(* The event used to check the file descriptor for readability. *)mutableevent_writable:Lwt_engine.eventoption;(* The event used to check the file descriptor for writability. *)hooks_readable:(unit->unit)Lwt_sequence.t;(* Hooks to call when the file descriptor becomes readable. *)hooks_writable:(unit->unit)Lwt_sequence.t;(* Hooks to call when the file descriptor becomes writable. *)}[@@@ocaml.warning"-3"]externalis_socket:Unix.file_descr->bool="lwt_unix_is_socket""noalloc"[@@@ocaml.warning"+3"]externalguess_blocking_job:Unix.file_descr->booljob="lwt_unix_guess_blocking_job"letguess_blockingfd=run_job(guess_blocking_jobfd)letis_blocking?blocking?(set_flags=true)fd=ifSys.win32thenbeginifis_socketfdthenmatchblocking,set_flagswith|Somestate,false->lazy(Lwt.returnstate)|Sometrue,true->lazy(Unix.clear_nonblockfd;Lwt.return_true)|Somefalse,true->lazy(Unix.set_nonblockfd;Lwt.return_false)|None,false->lazy(Lwt.return_false)|None,true->lazy(Unix.set_nonblockfd;Lwt.return_false)elsematchblockingwith|Somestate->lazy(Lwt.returnstate)|None->lazy(Lwt.return_true)endelsebeginmatchblocking,set_flagswith|Somestate,false->lazy(Lwt.returnstate)|Sometrue,true->lazy(Unix.clear_nonblockfd;Lwt.return_true)|Somefalse,true->lazy(Unix.set_nonblockfd;Lwt.return_false)|None,false->lazy(guess_blockingfd)|None,true->lazy(guess_blockingfd>>=function|true->Unix.clear_nonblockfd;Lwt.return_true|false->Unix.set_nonblockfd;Lwt.return_false)endletmk_ch?blocking?(set_flags=true)fd={fd=fd;state=Opened;set_flags=set_flags;blocking=is_blocking?blocking~set_flagsfd;event_readable=None;event_writable=None;hooks_readable=Lwt_sequence.create();hooks_writable=Lwt_sequence.create();}letcheck_descriptorch=matchch.statewith|Opened->()|Abortede->raisee|Closed->raise(Unix.Unix_error(Unix.EBADF,"check_descriptor",""))letstatech=ch.stateletblockingch=check_descriptorch;Lazy.forcech.blockingletset_blocking?(set_flags=true)chblocking=check_descriptorch;ch.set_flags<-set_flags;ch.blocking<-is_blocking~blocking~set_flagsch.fdexternalunix_stub_readable:Unix.file_descr->bool="lwt_unix_readable"externalunix_stub_writable:Unix.file_descr->bool="lwt_unix_writable"letrecunix_readablefd=tryifSys.win32thenUnix.select[fd][][]0.0<>([],[],[])elseunix_stub_readablefdwithUnix.Unix_error(Unix.EINTR,_,_)->unix_readablefdletrecunix_writablefd=tryifSys.win32thenUnix.select[][fd][]0.0<>([],[],[])elseunix_stub_writablefdwithUnix.Unix_error(Unix.EINTR,_,_)->unix_writablefdletreadablech=check_descriptorch;unix_readablech.fdletwritablech=check_descriptorch;unix_writablech.fdletset_statechst=ch.state<-stletclear_eventsch=Lwt_sequence.iter_node_l(funnode->Lwt_sequence.removenode;Lwt_sequence.getnode())ch.hooks_readable;Lwt_sequence.iter_node_l(funnode->Lwt_sequence.removenode;Lwt_sequence.getnode())ch.hooks_writable;beginmatchch.event_readablewith|Someev->ch.event_readable<-None;Lwt_engine.stop_eventev|None->()end;beginmatchch.event_writablewith|Someev->ch.event_writable<-None;Lwt_engine.stop_eventev|None->()endletabortche=ifch.state<>Closedthenbeginset_statech(Abortede);clear_eventschendletunix_file_descrch=ch.fdletof_unix_file_descr=mk_chletstdin=of_unix_file_descr~set_flags:false~blocking:trueUnix.stdinletstdout=of_unix_file_descr~set_flags:false~blocking:trueUnix.stdoutletstderr=of_unix_file_descr~set_flags:false~blocking:trueUnix.stderr(* +-----------------------------------------------------------------+
| Actions on file descriptors |
+-----------------------------------------------------------------+ *)typeio_event=Read|WriteexceptionRetryexceptionRetry_writeexceptionRetry_readtype'aoutcome=|Successof'a|Exnofexn|Requeuedofio_event(* Wait a bit, then stop events that are no more used. *)letstop_eventsch=Lwt.on_success(Lwt.pause())(fun()->ifLwt_sequence.is_emptych.hooks_readablethenbeginmatchch.event_readablewith|Someev->ch.event_readable<-None;Lwt_engine.stop_eventev|None->()end;ifLwt_sequence.is_emptych.hooks_writablethenbeginmatchch.event_writablewith|Someev->ch.event_writable<-None;Lwt_engine.stop_eventev|None->()end)letregister_readablech=ifch.event_readable=Nonethench.event_readable<-Some(Lwt_engine.on_readablech.fd(fun_->Lwt_sequence.iter_l(funf->f())ch.hooks_readable))letregister_writablech=ifch.event_writable=Nonethench.event_writable<-Some(Lwt_engine.on_writablech.fd(fun_->Lwt_sequence.iter_l(funf->f())ch.hooks_writable))(* Retry a queued syscall, [wakener] is the thread to wakeup if the
action succeeds: *)letrecretry_syscallnodeeventchwakeneraction=letres=trycheck_descriptorch;Success(action())with|Retry|Unix.Unix_error((Unix.EAGAIN|Unix.EWOULDBLOCK|Unix.EINTR),_,_)|Sys_blocked_io->(* EINTR because we are catching SIG_CHLD hence the system
call might be interrupted to handle the signal; this lets
us restart the system call eventually. *)Requeuedevent|Retry_read->RequeuedRead|Retry_write->RequeuedWrite|ewhenLwt.Exception_filter.rune->Exneinmatchreswith|Successv->Lwt_sequence.remove!node;stop_eventsch;Lwt.wakeupwakenerv|Exne->Lwt_sequence.remove!node;stop_eventsch;Lwt.wakeup_exnwakenere|Requeuedevent'->ifevent<>event'thenbeginLwt_sequence.remove!node;stop_eventsch;matchevent'with|Read->node:=Lwt_sequence.add_r(fun()->retry_syscallnodeReadchwakeneraction)ch.hooks_readable;register_readablech|Write->node:=Lwt_sequence.add_r(fun()->retry_syscallnodeWritechwakeneraction)ch.hooks_writable;register_writablechendletdummy=Lwt_sequence.add_rignore(Lwt_sequence.create())letregister_actioneventchaction=letwaiter,wakener=Lwt.task()inmatcheventwith|Read->letnode=refdummyinnode:=Lwt_sequence.add_r(fun()->retry_syscallnodeReadchwakeneraction)ch.hooks_readable;Lwt.on_cancelwaiter(fun()->Lwt_sequence.remove!node;stop_eventsch);register_readablech;waiter|Write->letnode=refdummyinnode:=Lwt_sequence.add_r(fun()->retry_syscallnodeWritechwakeneraction)ch.hooks_writable;Lwt.on_cancelwaiter(fun()->Lwt_sequence.remove!node;stop_eventsch);register_writablech;waiter(* Wraps a system call *)letwrap_syscalleventchaction=check_descriptorch;Lazy.forcech.blocking>>=funblocking->tryifnotblocking||(event=Read&&unix_readablech.fd)||(event=Write&&unix_writablech.fd)thenLwt.return(action())elseregister_actioneventchactionwith|Retry|Unix.Unix_error((Unix.EAGAIN|Unix.EWOULDBLOCK|Unix.EINTR),_,_)|Sys_blocked_io->(* The action could not be completed immediately, register it: *)register_actioneventchaction|Retry_read->register_actionReadchaction|Retry_write->register_actionWritechaction|ewhenLwt.Exception_filter.rune->Lwt.reraisee(* +-----------------------------------------------------------------+
| Basic file input/output |
+-----------------------------------------------------------------+ *)typeopen_flag=Unix.open_flag=|O_RDONLY|O_WRONLY|O_RDWR|O_NONBLOCK|O_APPEND|O_CREAT|O_TRUNC|O_EXCL|O_NOCTTY|O_DSYNC|O_SYNC|O_RSYNC|O_SHARE_DELETE|O_CLOEXEC|O_KEEPEXECexternalopen_job:string->Unix.open_flaglist->int->(Unix.file_descr*bool)job="lwt_unix_open_job"letopenfilenameflagsperms=ifSys.win32thenLwt.return(of_unix_file_descr(Unix.openfilenameflagsperms))elserun_job(open_jobnameflagsperms)>>=fun(fd,blocking)->Lwt.return(of_unix_file_descr~blockingfd)externalclose_job:Unix.file_descr->unitjob="lwt_unix_close_job"letclosech=ifch.state=Closedthencheck_descriptorch;set_statechClosed;clear_eventsch;ifSys.win32thenLwt.return(Unix.closech.fd)elserun_job(close_jobch.fd)typebigarray=(char,Bigarray.int8_unsigned_elt,Bigarray.c_layout)Bigarray.Array1.tletwait_readch=Lwt.catch(fun()->ifreadablechthenLwt.return_unitelseregister_actionReadchignore)Lwt.reraiseexternalstub_read:Unix.file_descr->Bytes.t->int->int->int="lwt_unix_read"externalread_job:Unix.file_descr->Bytes.t->int->int->intjob="lwt_unix_read_job"externalstub_pread:Unix.file_descr->Bytes.t->file_offset:int->int->int->int="lwt_unix_pread"externalpread_job:Unix.file_descr->Bytes.t->file_offset:int->int->int->intjob="lwt_unix_pread_job"letreadchbufposlen=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.read"elseLazy.forcech.blocking>>=function|true->wait_readch>>=fun()->run_job(read_jobch.fdbufposlen)|false->wrap_syscallReadch(fun()->stub_readch.fdbufposlen)letpreadchbuf~file_offsetposlen=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.pread"elseLazy.forcech.blocking>>=function|true->wait_readch>>=fun()->run_job(pread_jobch.fdbuf~file_offsetposlen)|false->wrap_syscallReadch(fun()->stub_preadch.fdbuf~file_offsetposlen)externalstub_read_bigarray:Unix.file_descr->bigarray->int->int->int="lwt_unix_bytes_read"externalread_bigarray_job:Unix.file_descr->bigarray->int->int->intjob="lwt_unix_bytes_read_job"letread_bigarrayfunction_namefdbufposlen=ifpos<0||len<0||pos>Bigarray.Array1.dimbuf-lentheninvalid_argfunction_nameelseblockingfd>>=function|true->wait_readfd>>=fun()->run_job(read_bigarray_job(unix_file_descrfd)bufposlen)|false->wrap_syscallReadfd(fun()->stub_read_bigarray(unix_file_descrfd)bufposlen)letwait_writech=Lwt.catch(fun()->ifwritablechthenLwt.return_unitelseregister_actionWritechignore)Lwt.reraiseexternalstub_write:Unix.file_descr->Bytes.t->int->int->int="lwt_unix_write"externalwrite_job:Unix.file_descr->Bytes.t->int->int->intjob="lwt_unix_write_job"externalstub_pwrite:Unix.file_descr->Bytes.t->file_offset:int->int->int->int="lwt_unix_pwrite"externalpwrite_job:Unix.file_descr->Bytes.t->file_offset:int->int->int->intjob="lwt_unix_pwrite_job"letwritechbufposlen=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.write"elseLazy.forcech.blocking>>=function|true->wait_writech>>=fun()->run_job(write_jobch.fdbufposlen)|false->wrap_syscallWritech(fun()->stub_writech.fdbufposlen)letpwritechbuf~file_offsetposlen=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.pwrite"elseLazy.forcech.blocking>>=function|true->wait_writech>>=fun()->run_job(pwrite_jobch.fdbuf~file_offsetposlen)|false->wrap_syscallWritech(fun()->stub_pwritech.fdbuf~file_offsetposlen)letwrite_stringchbufposlen=letbuf=Bytes.unsafe_of_stringbufinwritechbufposlenletpwrite_stringchbuf~file_offsetposlen=letbuf=Bytes.unsafe_of_stringbufinpwritechbuf~file_offsetposlenexternalstub_write_bigarray:Unix.file_descr->bigarray->int->int->int="lwt_unix_bytes_write"externalwrite_bigarray_job:Unix.file_descr->bigarray->int->int->intjob="lwt_unix_bytes_write_job"letwrite_bigarrayfunction_namefdbufposlen=ifpos<0||len<0||pos>Bigarray.Array1.dimbuf-lentheninvalid_argfunction_nameelseblockingfd>>=function|true->wait_writefd>>=fun()->run_job(write_bigarray_job(unix_file_descrfd)bufposlen)|false->wrap_syscallWritefd(fun()->stub_write_bigarray(unix_file_descrfd)bufposlen)moduleIO_vectors=structtype_bigarray=bigarraytypebuffer=|Bytesofbytes|Bigarrayof_bigarraytypeio_vector={buffer:buffer;mutableoffset:int;mutablelength:int}(* This representation does not give constant amortized time append across all
possible operation sequences, but it does for expected typical usage, in
which some number of append operations is followed by some number of
flatten operations. *)typet={mutableprefix:io_vectorlist;mutablereversed_suffix:io_vectorlist;mutablecount:int}letcreate()={prefix=[];reversed_suffix=[];count=0}letbyte_count{prefix;reversed_suffix;_}=letcount_buff=List.fold_left(funacc{length;_}->acc+length)0incount_buffprefix+count_buffreversed_suffixletappendio_vectorsio_vector=io_vectors.reversed_suffix<-io_vector::io_vectors.reversed_suffix;io_vectors.count<-io_vectors.count+1letappend_bytesio_vectorsbufferoffsetlength=appendio_vectors{buffer=Bytesbuffer;offset;length}letappend_bigarrayio_vectorsbufferoffsetlength=appendio_vectors{buffer=Bigarraybuffer;offset;length}letflattenio_vectors=matchio_vectors.reversed_suffixwith|[]->()|_->io_vectors.prefix<-io_vectors.prefix@(List.revio_vectors.reversed_suffix);io_vectors.reversed_suffix<-[]letdropio_vectorscount=flattenio_vectors;letrecloopcountprefix=ifcount<=0thenprefixelsematchprefixwith|[]->[]|{length;_}::restwhenlength<=count->io_vectors.count<-io_vectors.count-1;loop(count-length)rest|first::_->first.offset<-first.offset+count;first.length<-first.length-count;prefixinio_vectors.prefix<-loopcountio_vectors.prefixletis_emptyio_vectors=flattenio_vectors;letrecloop=function|[]->true|{length=0;_}::rest->looprest|_->falseinloopio_vectors.prefixexternalstub_iov_max:unit->intoption="lwt_unix_iov_max"letsystem_limit=ifSys.win32thenNoneelsestub_iov_max()letchecktagio_vector=letbuffer_length=matchio_vector.bufferwith|Bytess->Bytes.lengths|Bigarraya->Bigarray.Array1.dimainifio_vector.length<0||io_vector.offset<0||io_vector.offset+io_vector.length>buffer_lengththeninvalid_argtagend(* Flattens the I/O vectors into a single list, checks their bounds, and
evaluates to the minimum of: the number of vectors and the system's
IOV_MAX. *)letcheck_io_vectorsfunction_nameio_vectors=IO_vectors.flattenio_vectors;List.iter(IO_vectors.checkfunction_name)io_vectors.IO_vectors.prefix;matchIO_vectors.system_limitwith|Somelimitwhenio_vectors.IO_vectors.count>limit->limit|_->io_vectors.IO_vectors.countexternalstub_readv:Unix.file_descr->IO_vectors.io_vectorlist->int->int="lwt_unix_readv"externalreadv_job:Unix.file_descr->IO_vectors.t->int->intjob="lwt_unix_readv_job"letreadvfdio_vectors=letcount=check_io_vectors"Lwt_unix.readv"io_vectorsinifSys.win32thenmatchio_vectors.IO_vectors.prefixwith|[]->Lwt.return0|first::_->matchfirst.bufferwith|Bytesbuffer->readfdbufferfirst.offsetfirst.length|Bigarraybuffer->read_bigarray"Lwt_unix.readv"fdbufferfirst.offsetfirst.lengthelseLazy.forcefd.blocking>>=function|true->wait_readfd>>=fun()->run_job(readv_jobfd.fdio_vectorscount)|false->wrap_syscallReadfd(fun()->stub_readvfd.fdio_vectors.IO_vectors.prefixcount)externalstub_writev:Unix.file_descr->IO_vectors.io_vectorlist->int->int="lwt_unix_writev"externalwritev_job:Unix.file_descr->IO_vectors.t->int->intjob="lwt_unix_writev_job"letwritevfdio_vectors=letcount=check_io_vectors"Lwt_unix.writev"io_vectorsinifSys.win32thenmatchio_vectors.IO_vectors.prefixwith|[]->Lwt.return0|first::_->matchfirst.bufferwith|Bytesbuffer->writefdbufferfirst.offsetfirst.length|Bigarraybuffer->write_bigarray"Lwt_unix.writev"fdbufferfirst.offsetfirst.lengthelseLazy.forcefd.blocking>>=function|true->wait_writefd>>=fun()->run_job(writev_jobfd.fdio_vectorscount)|false->wrap_syscallWritefd(fun()->stub_writevfd.fdio_vectors.IO_vectors.prefixcount)(* +-----------------------------------------------------------------+
| Seeking and truncating |
+-----------------------------------------------------------------+ *)typeseek_command=Unix.seek_command=|SEEK_SET|SEEK_CUR|SEEK_ENDexternallseek_job:Unix.file_descr->int->Unix.seek_command->intjob="lwt_unix_lseek_job"letlseekchoffsetwhence=check_descriptorch;ifSys.win32thenLwt.return(Unix.lseekch.fdoffsetwhence)elserun_job(lseek_jobch.fdoffsetwhence)externaltruncate_job:string->int->unitjob="lwt_unix_truncate_job"lettruncatenameoffset=ifSys.win32thenLwt.return(Unix.truncatenameoffset)elserun_job(truncate_jobnameoffset)externalftruncate_job:Unix.file_descr->int->unitjob="lwt_unix_ftruncate_job"letftruncatechoffset=check_descriptorch;ifSys.win32thenLwt.return(Unix.ftruncatech.fdoffset)elserun_job(ftruncate_jobch.fdoffset)(* +-----------------------------------------------------------------+
| File system synchronisation |
+-----------------------------------------------------------------+ *)externalfdatasync_job:Unix.file_descr->unitjob="lwt_unix_fdatasync_job"letfdatasyncch=check_descriptorch;run_job(fdatasync_jobch.fd)externalfsync_job:Unix.file_descr->unitjob="lwt_unix_fsync_job"letfsyncch=check_descriptorch;run_job(fsync_jobch.fd)(* +-----------------------------------------------------------------+
| File status |
+-----------------------------------------------------------------+ *)typefile_perm=Unix.file_permtypefile_kind=Unix.file_kind=|S_REG|S_DIR|S_CHR|S_BLK|S_LNK|S_FIFO|S_SOCKtypestats=Unix.stats={st_dev:int;st_ino:int;st_kind:file_kind;st_perm:file_perm;st_nlink:int;st_uid:int;st_gid:int;st_rdev:int;st_size:int;st_atime:float;st_mtime:float;st_ctime:float;}externalstat_job:string->Unix.statsjob="lwt_unix_stat_job"letstatname=ifSys.win32thenLwt.return(Unix.statname)elserun_job(stat_jobname)externallstat_job:string->Unix.statsjob="lwt_unix_lstat_job"letlstatname=ifSys.win32thenLwt.return(Unix.lstatname)elserun_job(lstat_jobname)externalfstat_job:Unix.file_descr->Unix.statsjob="lwt_unix_fstat_job"letfstatch=check_descriptorch;ifSys.win32thenLwt.return(Unix.fstatch.fd)elserun_job(fstat_jobch.fd)letfile_existsname=Lwt.try_bind(fun()->statname)(fun_->Lwt.return_true)(fune->matchewith|Unix.Unix_error_->Lwt.return_false|_->Lwt.reraisee)[@ocaml.warning"-4"]externalutimes_job:string->float->float->unitjob="lwt_unix_utimes_job"letutimespathatimemtime=ifSys.win32thenLwt.return(Unix.utimespathatimemtime)elserun_job(utimes_jobpathatimemtime)externalisatty_job:Unix.file_descr->booljob="lwt_unix_isatty_job"letisattych=check_descriptorch;ifSys.win32thenLwt.return(Unix.isattych.fd)elserun_job(isatty_jobch.fd)(* +-----------------------------------------------------------------+
| File operations on large files |
+-----------------------------------------------------------------+ *)moduleLargeFile=structtypestats=Unix.LargeFile.stats={st_dev:int;st_ino:int;st_kind:file_kind;st_perm:file_perm;st_nlink:int;st_uid:int;st_gid:int;st_rdev:int;st_size:int64;st_atime:float;st_mtime:float;st_ctime:float;}externallseek_64_job:Unix.file_descr->int64->Unix.seek_command->int64job="lwt_unix_lseek_64_job"letlseekchoffsetwhence=check_descriptorch;ifSys.win32thenLwt.return(Unix.LargeFile.lseekch.fdoffsetwhence)elserun_job(lseek_64_jobch.fdoffsetwhence)externaltruncate_64_job:string->int64->unitjob="lwt_unix_truncate_64_job"lettruncatenameoffset=ifSys.win32thenLwt.return(Unix.LargeFile.truncatenameoffset)elserun_job(truncate_64_jobnameoffset)externalftruncate_64_job:Unix.file_descr->int64->unitjob="lwt_unix_ftruncate_64_job"letftruncatechoffset=check_descriptorch;ifSys.win32thenLwt.return(Unix.LargeFile.ftruncatech.fdoffset)elserun_job(ftruncate_64_jobch.fdoffset)externalstat_job:string->Unix.LargeFile.statsjob="lwt_unix_stat_64_job"letstatname=ifSys.win32thenLwt.return(Unix.LargeFile.statname)elserun_job(stat_jobname)externallstat_job:string->Unix.LargeFile.statsjob="lwt_unix_lstat_64_job"letlstatname=ifSys.win32thenLwt.return(Unix.LargeFile.lstatname)elserun_job(lstat_jobname)externalfstat_job:Unix.file_descr->Unix.LargeFile.statsjob="lwt_unix_fstat_64_job"letfstatch=check_descriptorch;ifSys.win32thenLwt.return(Unix.LargeFile.fstatch.fd)elserun_job(fstat_jobch.fd)letfile_existsname=Lwt.try_bind(fun()->statname)(fun_->Lwt.return_true)(fune->matchewith|Unix.Unix_error_->Lwt.return_false|_->Lwt.reraisee)[@ocaml.warning"-4"]end(* +-----------------------------------------------------------------+
| Operations on file names |
+-----------------------------------------------------------------+ *)externalunlink_job:string->unitjob="lwt_unix_unlink_job"letunlinkname=ifSys.win32thenLwt.return(Unix.unlinkname)elserun_job(unlink_jobname)externalrename_job:string->string->unitjob="lwt_unix_rename_job"letrenamename1name2=ifSys.win32thenLwt.return(Unix.renamename1name2)elserun_job(rename_jobname1name2)externallink_job:string->string->unitjob="lwt_unix_link_job"letlinkoldpathnewpath=ifSys.win32thenLwt.return(Unix.linkoldpathnewpath)elserun_job(link_joboldpathnewpath)(* +-----------------------------------------------------------------+
| File permissions and ownership |
+-----------------------------------------------------------------+ *)externalchmod_job:string->int->unitjob="lwt_unix_chmod_job"letchmodnamemode=ifSys.win32thenLwt.return(Unix.chmodnamemode)elserun_job(chmod_jobnamemode)externalfchmod_job:Unix.file_descr->int->unitjob="lwt_unix_fchmod_job"letfchmodchmode=check_descriptorch;ifSys.win32thenLwt.return(Unix.fchmodch.fdmode)elserun_job(fchmod_jobch.fdmode)externalchown_job:string->int->int->unitjob="lwt_unix_chown_job"letchownnameuidgid=ifSys.win32thenLwt.return(Unix.chownnameuidgid)elserun_job(chown_jobnameuidgid)externalfchown_job:Unix.file_descr->int->int->unitjob="lwt_unix_fchown_job"letfchownchuidgid=check_descriptorch;ifSys.win32thenLwt.return(Unix.fchownch.fduidgid)elserun_job(fchown_jobch.fduidgid)typeaccess_permission=Unix.access_permission=|R_OK|W_OK|X_OK|F_OKexternalaccess_job:string->Unix.access_permissionlist->unitjob="lwt_unix_access_job"letaccessnamemode=ifSys.win32thenLwt.return(Unix.accessnamemode)elserun_job(access_jobnamemode)(* +-----------------------------------------------------------------+
| Operations on file descriptors |
+-----------------------------------------------------------------+ *)letdup?cloexecch=check_descriptorch;letfd=Unix.dup?cloexecch.fdin{fd=fd;state=Opened;set_flags=ch.set_flags;blocking=ifch.set_flagsthenlazy(Lazy.forcech.blocking>>=functionblocking->Lazy.force(is_blocking~blockingfd))elsech.blocking;event_readable=None;event_writable=None;hooks_readable=Lwt_sequence.create();hooks_writable=Lwt_sequence.create();}letdup2?cloexecch1ch2=check_descriptorch1;Unix.dup2?cloexecch1.fdch2.fd;ch2.set_flags<-ch1.set_flags;ch2.blocking<-(ifch2.set_flagsthenlazy(Lazy.forcech1.blocking>>=functionblocking->Lazy.force(is_blocking~blockingch2.fd))elsech1.blocking)letset_close_on_execch=check_descriptorch;Unix.set_close_on_execch.fdletclear_close_on_execch=check_descriptorch;Unix.clear_close_on_execch.fd(* +-----------------------------------------------------------------+
| Directories |
+-----------------------------------------------------------------+ *)externalmkdir_job:string->int->unitjob="lwt_unix_mkdir_job"letmkdirnameperms=ifSys.win32thenLwt.return(Unix.mkdirnameperms)elserun_job(mkdir_jobnameperms)externalrmdir_job:string->unitjob="lwt_unix_rmdir_job"letrmdirname=ifSys.win32thenLwt.return(Unix.rmdirname)elserun_job(rmdir_jobname)externalchdir_job:string->unitjob="lwt_unix_chdir_job"letchdirname=ifSys.win32thenLwt.return(Unix.chdirname)elserun_job(chdir_jobname)externalgetcwd_job:unit->stringjob="lwt_unix_getcwd_job"letgetcwd()=ifSys.win32thenLwt.return(Unix.getcwd())elserun_job(getcwd_job())externalchroot_job:string->unitjob="lwt_unix_chroot_job"letchrootname=ifSys.win32thenLwt.return(Unix.chrootname)elserun_job(chroot_jobname)typedir_handle=Unix.dir_handleexternalopendir_job:string->Unix.dir_handlejob="lwt_unix_opendir_job"letopendirname=ifSys.win32thenLwt.return(Unix.opendirname)elserun_job(opendir_jobname)externalvalid_dir:Unix.dir_handle->bool="lwt_unix_valid_dir"externalreaddir_job:Unix.dir_handle->stringjob="lwt_unix_readdir_job"letreaddirhandle=ifSys.win32thenLwt.return(Unix.readdirhandle)elseifvalid_dirhandlethenrun_job(readdir_jobhandle)elseLwt.fail(Unix.(Unix_error(EBADF,"Lwt_unix.readdir","")))externalreaddir_n_job:Unix.dir_handle->int->stringarrayjob="lwt_unix_readdir_n_job"letreaddir_nhandlecount=ifcount<0thenLwt.fail(Invalid_argument"Lwt_unix.readdir_n")elseifSys.win32thenletarray=Array.makecount""inletrecfilli=ifi=countthenLwt.returnarrayelsematcharray.(i)<-Unix.readdirhandlewith|exceptionEnd_of_file->Lwt.return(Array.subarray0i)|()->fill(i+1)infill0elseifvalid_dirhandlethenrun_job(readdir_n_jobhandlecount)elseLwt.fail(Unix.(Unix_error(EBADF,"Lwt_unix.readdir_n","")))externalrewinddir_job:Unix.dir_handle->unitjob="lwt_unix_rewinddir_job"letrewinddirhandle=ifSys.win32thenLwt.return(Unix.rewinddirhandle)elseifvalid_dirhandlethenrun_job(rewinddir_jobhandle)elseLwt.fail(Unix.(Unix_error(EBADF,"Lwt_unix.rewinddir","")))externalclosedir_job:Unix.dir_handle->unitjob="lwt_unix_closedir_job"externalinvalidate_dir:Unix.dir_handle->unit="lwt_unix_invalidate_dir"letclosedirhandle=ifSys.win32thenLwt.return(Unix.closedirhandle)elseifvalid_dirhandlethenrun_job(closedir_jobhandle)>>=fun()->invalidate_dirhandle;Lwt.return_unitelseLwt.fail(Unix.(Unix_error(EBADF,"Lwt_unix.closedir","")))typelist_directory_state=|LDS_not_started|LDS_listingofUnix.dir_handle|LDS_doneletcleanup_dir_handlestate=match!statewith|LDS_listinghandle->ignore(closedirhandle)|LDS_not_started|LDS_done->()letfiles_of_directorypath=letchunk_size=1024inletstate=refLDS_not_startedinLwt_stream.concat(Lwt_stream.from(fun()->match!statewith|LDS_not_started->opendirpath>>=funhandle->Lwt.catch(fun()->readdir_nhandlechunk_size)(funexn->closedirhandle>>=fun()->Lwt.reraiseexn)>>=funentries->ifArray.lengthentries<chunk_sizethenbeginstate:=LDS_done;closedirhandle>>=fun()->Lwt.return(Some(Lwt_stream.of_arrayentries))endelsebeginstate:=LDS_listinghandle;Gc.finalisecleanup_dir_handlestate;Lwt.return(Some(Lwt_stream.of_arrayentries))end|LDS_listinghandle->Lwt.catch(fun()->readdir_nhandlechunk_size)(funexn->closedirhandle>>=fun()->Lwt.reraiseexn)>>=funentries->ifArray.lengthentries<chunk_sizethenbeginstate:=LDS_done;closedirhandle>>=fun()->Lwt.return(Some(Lwt_stream.of_arrayentries))endelseLwt.return(Some(Lwt_stream.of_arrayentries))|LDS_done->Lwt.return_none))(* +-----------------------------------------------------------------+
| Pipes and redirections |
+-----------------------------------------------------------------+ *)letpipe?cloexec()=let(out_fd,in_fd)=Unix.pipe?cloexec()in(mk_ch~blocking:Sys.win32out_fd,mk_ch~blocking:Sys.win32in_fd)letpipe_in?cloexec()=let(out_fd,in_fd)=Unix.pipe?cloexec()in(mk_ch~blocking:Sys.win32out_fd,in_fd)letpipe_out?cloexec()=let(out_fd,in_fd)=Unix.pipe?cloexec()in(out_fd,mk_ch~blocking:Sys.win32in_fd)externalmkfifo_job:string->int->unitjob="lwt_unix_mkfifo_job"letmkfifonameperms=ifSys.win32thenLwt.return(Unix.mkfifonameperms)elserun_job(mkfifo_jobnameperms)(* +-----------------------------------------------------------------+
| Symbolic links |
+-----------------------------------------------------------------+ *)externalsymlink_job:string->string->unitjob="lwt_unix_symlink_job"letsymlink?to_dirname1name2=ifSys.win32thenLwt.return(Unix.symlink?to_dirname1name2)elserun_job(symlink_jobname1name2)externalreadlink_job:string->stringjob="lwt_unix_readlink_job"letreadlinkname=ifSys.win32thenLwt.return(Unix.readlinkname)elserun_job(readlink_jobname)(* +-----------------------------------------------------------------+
| Locking |
+-----------------------------------------------------------------+ *)typelock_command=Unix.lock_command=|F_ULOCK|F_LOCK|F_TLOCK|F_TEST|F_RLOCK|F_TRLOCKexternallockf_job:Unix.file_descr->Unix.lock_command->int->unitjob="lwt_unix_lockf_job"letlockfchcmdsize=check_descriptorch;ifSys.win32thenLwt.return(Unix.lockfch.fdcmdsize)elserun_job(lockf_jobch.fdcmdsize)(* +-----------------------------------------------------------------+
| User id, group id |
+-----------------------------------------------------------------+ *)typepasswd_entry=Unix.passwd_entry={pw_name:string;pw_passwd:string;pw_uid:int;pw_gid:int;pw_gecos:string;pw_dir:string;pw_shell:string}typegroup_entry=Unix.group_entry={gr_name:string;gr_passwd:string;gr_gid:int;gr_mem:stringarray}externalgetlogin_job:unit->stringjob="lwt_unix_getlogin_job"letgetlogin()=ifSys.win32||Lwt_config.androidthenLwt.return(Unix.getlogin())elserun_job(getlogin_job())externalgetpwnam_job:string->Unix.passwd_entryjob="lwt_unix_getpwnam_job"letgetpwnamname=ifSys.win32||Lwt_config.androidthenLwt.return(Unix.getpwnamname)elserun_job(getpwnam_jobname)externalgetgrnam_job:string->Unix.group_entryjob="lwt_unix_getgrnam_job"letgetgrnamname=ifSys.win32||Lwt_config.androidthenLwt.return(Unix.getgrnamname)elserun_job(getgrnam_jobname)externalgetpwuid_job:int->Unix.passwd_entryjob="lwt_unix_getpwuid_job"letgetpwuiduid=ifSys.win32||Lwt_config.androidthenLwt.return(Unix.getpwuiduid)elserun_job(getpwuid_jobuid)externalgetgrgid_job:int->Unix.group_entryjob="lwt_unix_getgrgid_job"letgetgrgidgid=ifSys.win32||Lwt_config.androidthenLwt.return(Unix.getgrgidgid)elserun_job(getgrgid_jobgid)(* +-----------------------------------------------------------------+
| Sockets |
+-----------------------------------------------------------------+ *)typemsg_flag=Unix.msg_flag=|MSG_OOB|MSG_DONTROUTE|MSG_PEEKexternalstub_recv:Unix.file_descr->Bytes.t->int->int->Unix.msg_flaglist->int="lwt_unix_recv"letrecvchbufposlenflags=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.recv"elseletdo_recv=ifSys.win32thenUnix.recvelsestub_recvinwrap_syscallReadch(fun()->do_recvch.fdbufposlenflags)externalstub_send:Unix.file_descr->Bytes.t->int->int->Unix.msg_flaglist->int="lwt_unix_send"letsendchbufposlenflags=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.send"elseletdo_send=ifSys.win32thenUnix.sendelsestub_sendinwrap_syscallWritech(fun()->do_sendch.fdbufposlenflags)externalstub_recvfrom:Unix.file_descr->Bytes.t->int->int->Unix.msg_flaglist->int*Unix.sockaddr="lwt_unix_recvfrom"letrecvfromchbufposlenflags=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.recvfrom"elseletdo_recvfrom=ifSys.win32thenUnix.recvfromelsestub_recvfrominwrap_syscallReadch(fun()->do_recvfromch.fdbufposlenflags)externalstub_sendto:Unix.file_descr->Bytes.t->int->int->Unix.msg_flaglist->Unix.sockaddr->int="lwt_unix_sendto_byte""lwt_unix_sendto"letsendtochbufposlenflagsaddr=ifpos<0||len<0||pos>Bytes.lengthbuf-lentheninvalid_arg"Lwt_unix.sendto"elseletdo_sendto=ifSys.win32thenUnix.sendtoelsestub_sendtoinwrap_syscallWritech(fun()->do_sendtoch.fdbufposlenflagsaddr)externalstub_recv_msg:Unix.file_descr->int->IO_vectors.io_vectorlist->int*Unix.file_descrlist="lwt_unix_recv_msg"letrecv_msg~socket~io_vectors=letcount=check_io_vectors"Lwt_unix.recv_msg"io_vectorsinwrap_syscallReadsocket(fun()->stub_recv_msgsocket.fdcountio_vectors.IO_vectors.prefix)externalstub_send_msg:Unix.file_descr->int->IO_vectors.io_vectorlist->int->Unix.file_descrlist->Unix.sockaddroption->int="lwt_unix_send_msg_byte""lwt_unix_send_msg"letsend_msg~socket~io_vectors~fds=letvector_count=check_io_vectors"Lwt_unix.send_msg"io_vectorsinletfd_count=List.lengthfdsinwrap_syscallWritesocket(fun()->stub_send_msgsocket.fdvector_countio_vectors.IO_vectors.prefixfd_countfdsNone)letsend_msgto~socket~io_vectors~fds~dest=letvector_count=check_io_vectors"Lwt_unix.send_msgto"io_vectorsinletfd_count=List.lengthfdsinwrap_syscallWritesocket(fun()->stub_send_msgsocket.fdvector_countio_vectors.IO_vectors.prefixfd_countfds(Somedest))typeinet_addr=Unix.inet_addrtypesocket_domain=Unix.socket_domain=|PF_UNIX|PF_INET|PF_INET6typesocket_type=Unix.socket_type=|SOCK_STREAM|SOCK_DGRAM|SOCK_RAW|SOCK_SEQPACKETtypesockaddr=Unix.sockaddr=ADDR_UNIXofstring|ADDR_INETofinet_addr*intletsocket?cloexecdomtypproto=lets=Unix.socket?cloexecdomtypprotoinmk_ch~blocking:falsestypeshutdown_command=Unix.shutdown_command=|SHUTDOWN_RECEIVE|SHUTDOWN_SEND|SHUTDOWN_ALLletshutdownchshutdown_command=check_descriptorch;Unix.shutdownch.fdshutdown_commandexternalstub_socketpair:?cloexec:bool->socket_domain->socket_type->int->Unix.file_descr*Unix.file_descr="lwt_unix_socketpair_stub"letsocketpair?cloexecdomtypproto=let(s1,s2)=# 1683 "src/unix/lwt_unix.cppo.ml"ifSys.win32thenstub_socketpair?cloexecdomtypprotoelsebeginlet(s1,s2)=Unix.socketpairdomtypprotoinifcloexec=SometruethenbeginUnix.set_close_on_execs1;Unix.set_close_on_execs2end;(s1,s2)endin# 1693 "src/unix/lwt_unix.cppo.ml"(mk_ch~blocking:falses1,mk_ch~blocking:falses2)externalaccept4:?cloexec:bool->nonblock:bool->Unix.file_descr->Unix.file_descr*Unix.sockaddr="lwt_unix_accept4"letaccept_and_set_nonblock?cloexecch_fd=ifLwt_config._HAVE_ACCEPT4thenlet(fd,addr)=accept4?cloexec~nonblock:truech_fdin(mk_ch~blocking:false~set_flags:falsefd,addr)elselet(fd,addr)=Unix.accept?cloexecch_fdin(mk_ch~blocking:falsefd,addr)letaccept?cloexecch=wrap_syscallReadch(fun_->accept_and_set_nonblock?cloexecch.fd)letaccept_n?cloexecchn=letl=ref[]inLazy.forcech.blocking>>=funblocking->Lwt.catch(fun()->wrap_syscallReadchbeginfun()->begintryfor_i=1tondoifblocking&¬(unix_readablech.fd)thenraiseRetry;l:=accept_and_set_nonblock?cloexecch.fd::!ldonewith|(Unix.Unix_error((Unix.EAGAIN|Unix.EWOULDBLOCK|Unix.EINTR),_,_)|Retry)when!l<>[]->(* Ignore blocking errors if we have at least one file-descriptor: *)()end;(List.rev!l,None)end)(funexn->Lwt.return(List.rev!l,Someexn))letconnectchaddr=ifSys.win32then(* [in_progress] tell whether connection has started but not
terminated: *)letin_progress=reffalseinwrap_syscallWritechbeginfun()->if!in_progressthen(* Nothing works without this test and i have no idea why... *)ifwritablechthentryUnix.connectch.fdaddrwith|Unix.Unix_error(Unix.EISCONN,_,_)->(* This is the windows way of telling that the connection
has completed. *)()elseraiseRetryelsetryUnix.connectch.fdaddrwith|Unix.Unix_error(Unix.EWOULDBLOCK,_,_)->in_progress:=true;raiseRetryendelse(* [in_progress] tell whether connection has started but not
terminated: *)letin_progress=reffalseinwrap_syscallWritechbeginfun()->if!in_progressthen(* If the connection is in progress, [getsockopt_error] tells
whether it succceed: *)matchUnix.getsockopt_errorch.fdwith|None->(* The socket is connected *)()|Someerr->(* An error happened: *)raise(Unix.Unix_error(err,"connect",""))elsetry(* We should pass only one time here, unless the system call
is interrupted by a signal: *)Unix.connectch.fdaddrwith|Unix.Unix_error(Unix.EINPROGRESS,_,_)->in_progress:=true;raiseRetryendexternalbind_job:Unix.file_descr->Unix.sockaddr->unitjob="lwt_unix_bind_job"letbindfdaddr=check_descriptorfd;matchSys.win32,addrwith|true,_|false,Unix.ADDR_INET_->Lwt.return(Unix.bindfd.fdaddr)|false,Unix.ADDR_UNIX_->run_job(bind_jobfd.fdaddr)letlistenchcnt=check_descriptorch;Unix.listench.fdcntexternalsomaxconn:unit->int="lwt_unix_somaxconn"letgetpeernamech=check_descriptorch;Unix.getpeernamech.fdletgetsocknamech=check_descriptorch;Unix.getsocknamech.fdtypecredentials={cred_pid:int;cred_uid:int;cred_gid:int;}externalstub_get_credentials:Unix.file_descr->credentials="lwt_unix_get_credentials"letget_credentialsch=check_descriptorch;stub_get_credentialsch.fd(* +-----------------------------------------------------------------+
| Socket options |
+-----------------------------------------------------------------+ *)typesocket_bool_option=Unix.socket_bool_option=|SO_DEBUG|SO_BROADCAST|SO_REUSEADDR|SO_KEEPALIVE|SO_DONTROUTE|SO_OOBINLINE|SO_ACCEPTCONN|TCP_NODELAY|IPV6_ONLY# 1837 "src/unix/lwt_unix.cppo.ml"typesocket_int_option=Unix.socket_int_option=|SO_SNDBUF|SO_RCVBUF|SO_ERROR[@ocaml.deprecated"Use Unix.getsockopt_error instead."]|SO_TYPE|SO_RCVLOWAT|SO_SNDLOWATtypesocket_optint_option=Unix.socket_optint_option=SO_LINGERtypesocket_float_option=Unix.socket_float_option=|SO_RCVTIMEO|SO_SNDTIMEOletgetsockoptchopt=check_descriptorch;Unix.getsockoptch.fdoptletsetsockoptchoptx=check_descriptorch;Unix.setsockoptch.fdoptxletgetsockopt_intchopt=check_descriptorch;Unix.getsockopt_intch.fdoptletsetsockopt_intchoptx=check_descriptorch;Unix.setsockopt_intch.fdoptxletgetsockopt_optintchopt=check_descriptorch;Unix.getsockopt_optintch.fdoptletsetsockopt_optintchoptx=check_descriptorch;Unix.setsockopt_optintch.fdoptxletgetsockopt_floatchopt=check_descriptorch;Unix.getsockopt_floatch.fdoptletsetsockopt_floatchoptx=check_descriptorch;Unix.setsockopt_floatch.fdoptxletgetsockopt_errorch=check_descriptorch;Unix.getsockopt_errorch.fd(* +-----------------------------------------------------------------+
| Multicast functions |
+-----------------------------------------------------------------+ *)externalstub_mcast_set_loop:Unix.file_descr->bool->unit="lwt_unix_mcast_set_loop"externalstub_mcast_set_ttl:Unix.file_descr->int->unit="lwt_unix_mcast_set_ttl"typemcast_action=Add|Dropexternalstub_mcast_modify_membership:Unix.file_descr->mcast_action->Unix.inet_addr->Unix.inet_addr->unit="lwt_unix_mcast_modify_membership"letmcast_set_loopchflag=check_descriptorch;stub_mcast_set_loopch.fdflagletmcast_set_ttlchttl=check_descriptorch;stub_mcast_set_ttlch.fdttlletmcast_add_membershipch?(ifname=Unix.inet_addr_any)addr=check_descriptorch;stub_mcast_modify_membershipch.fdAddifnameaddrletmcast_drop_membershipch?(ifname=Unix.inet_addr_any)addr=check_descriptorch;stub_mcast_modify_membershipch.fdDropifnameaddr(* +-----------------------------------------------------------------+
| Host and protocol databases |
+-----------------------------------------------------------------+ *)typehost_entry=Unix.host_entry={h_name:string;h_aliases:stringarray;h_addrtype:socket_domain;h_addr_list:inet_addrarray}typeprotocol_entry=Unix.protocol_entry={p_name:string;p_aliases:stringarray;p_proto:int}typeservice_entry=Unix.service_entry={s_name:string;s_aliases:stringarray;s_port:int;s_proto:string}externalgethostname_job:unit->stringjob="lwt_unix_gethostname_job"letgethostname()=ifSys.win32thenLwt.return(Unix.gethostname())elserun_job(gethostname_job())lethostent_mutex=Lwt_mutex.create()externalgethostbyname_job:string->Unix.host_entryjob="lwt_unix_gethostbyname_job"letgethostbynamename=ifSys.win32thenLwt.return(Unix.gethostbynamename)elseifLwt_config._HAVE_REENTRANT_HOSTENTthenrun_job(gethostbyname_jobname)elseLwt_mutex.with_lockhostent_mutex(fun()->run_job(gethostbyname_jobname))externalgethostbyaddr_job:Unix.inet_addr->Unix.host_entryjob="lwt_unix_gethostbyaddr_job"letgethostbyaddraddr=ifSys.win32thenLwt.return(Unix.gethostbyaddraddr)elseifLwt_config._HAVE_REENTRANT_HOSTENTthenrun_job(gethostbyaddr_jobaddr)elseLwt_mutex.with_lockhostent_mutex(fun()->run_job(gethostbyaddr_jobaddr))letprotoent_mutex=ifSys.win32||Lwt_config._HAVE_NETDB_REENTRANTthenhostent_mutexelseLwt_mutex.create()externalgetprotobyname_job:string->Unix.protocol_entryjob="lwt_unix_getprotobyname_job"letgetprotobynamename=ifSys.win32thenLwt.return(Unix.getprotobynamename)elseifLwt_config._HAVE_NETDB_REENTRANTthenrun_job(getprotobyname_jobname)elseLwt_mutex.with_lockprotoent_mutex(fun()->run_job(getprotobyname_jobname))externalgetprotobynumber_job:int->Unix.protocol_entryjob="lwt_unix_getprotobynumber_job"letgetprotobynumbernumber=ifSys.win32thenLwt.return(Unix.getprotobynumbernumber)elseifLwt_config._HAVE_NETDB_REENTRANTthenrun_job(getprotobynumber_jobnumber)elseLwt_mutex.with_lockprotoent_mutex(fun()->run_job(getprotobynumber_jobnumber))(* TODO: Not used anywhere, and that might be a bug. *)let_servent_mutex=ifSys.win32||Lwt_config._HAVE_NETDB_REENTRANTthenhostent_mutexelseLwt_mutex.create()externalgetservbyname_job:string->string->Unix.service_entryjob="lwt_unix_getservbyname_job"letgetservbynamenamex=ifSys.win32thenLwt.return(Unix.getservbynamenamex)elseifLwt_config._HAVE_NETDB_REENTRANTthenrun_job(getservbyname_jobnamex)elseLwt_mutex.with_lockprotoent_mutex(fun()->run_job(getservbyname_jobnamex))externalgetservbyport_job:int->string->Unix.service_entryjob="lwt_unix_getservbyport_job"letgetservbyportportx=ifSys.win32thenLwt.return(Unix.getservbyportportx)elseifLwt_config._HAVE_NETDB_REENTRANTthenrun_job(getservbyport_jobportx)elseLwt_mutex.with_lockprotoent_mutex(fun()->run_job(getservbyport_jobportx))typeaddr_info=Unix.addr_info={ai_family:socket_domain;ai_socktype:socket_type;ai_protocol:int;ai_addr:sockaddr;ai_canonname:string;}typegetaddrinfo_option=Unix.getaddrinfo_option=|AI_FAMILYofsocket_domain|AI_SOCKTYPEofsocket_type|AI_PROTOCOLofint|AI_NUMERICHOST|AI_CANONNAME|AI_PASSIVEexternalgetaddrinfo_job:string->string->Unix.getaddrinfo_optionlist->Unix.addr_infolistjob="lwt_unix_getaddrinfo_job"letgetaddrinfohostserviceopts=ifSys.win32thenLwt.return(Unix.getaddrinfohostserviceopts)elserun_job(getaddrinfo_jobhostserviceopts)>>=funl->Lwt.return(List.revl)typename_info=Unix.name_info={ni_hostname:string;ni_service:string;}typegetnameinfo_option=Unix.getnameinfo_option=|NI_NOFQDN|NI_NUMERICHOST|NI_NAMEREQD|NI_NUMERICSERV|NI_DGRAMexternalgetnameinfo_job:Unix.sockaddr->Unix.getnameinfo_optionlist->Unix.name_infojob="lwt_unix_getnameinfo_job"letgetnameinfoaddropts=ifSys.win32thenLwt.return(Unix.getnameinfoaddropts)elserun_job(getnameinfo_jobaddropts)(* +-----------------------------------------------------------------+
| Terminal interface |
+-----------------------------------------------------------------+ *)typeterminal_io=Unix.terminal_io={mutablec_ignbrk:bool;mutablec_brkint:bool;mutablec_ignpar:bool;mutablec_parmrk:bool;mutablec_inpck:bool;mutablec_istrip:bool;mutablec_inlcr:bool;mutablec_igncr:bool;mutablec_icrnl:bool;mutablec_ixon:bool;mutablec_ixoff:bool;mutablec_opost:bool;mutablec_obaud:int;mutablec_ibaud:int;mutablec_csize:int;mutablec_cstopb:int;mutablec_cread:bool;mutablec_parenb:bool;mutablec_parodd:bool;mutablec_hupcl:bool;mutablec_clocal:bool;mutablec_isig:bool;mutablec_icanon:bool;mutablec_noflsh:bool;mutablec_echo:bool;mutablec_echoe:bool;mutablec_echok:bool;mutablec_echonl:bool;mutablec_vintr:char;mutablec_vquit:char;mutablec_verase:char;mutablec_vkill:char;mutablec_veof:char;mutablec_veol:char;mutablec_vmin:int;mutablec_vtime:int;mutablec_vstart:char;mutablec_vstop:char;}typesetattr_when=Unix.setattr_when=|TCSANOW|TCSADRAIN|TCSAFLUSHtypeflush_queue=Unix.flush_queue=|TCIFLUSH|TCOFLUSH|TCIOFLUSHtypeflow_action=Unix.flow_action=|TCOOFF|TCOON|TCIOFF|TCIONexternaltcgetattr_job:Unix.file_descr->Unix.terminal_iojob="lwt_unix_tcgetattr_job"lettcgetattrch=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcgetattrch.fd)elserun_job(tcgetattr_jobch.fd)externaltcsetattr_job:Unix.file_descr->Unix.setattr_when->Unix.terminal_io->unitjob="lwt_unix_tcsetattr_job"lettcsetattrchwhen_attrs=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcsetattrch.fdwhen_attrs)elserun_job(tcsetattr_jobch.fdwhen_attrs)externaltcsendbreak_job:Unix.file_descr->int->unitjob="lwt_unix_tcsendbreak_job"lettcsendbreakchdelay=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcsendbreakch.fddelay)elserun_job(tcsendbreak_jobch.fddelay)externaltcdrain_job:Unix.file_descr->unitjob="lwt_unix_tcdrain_job"lettcdrainch=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcdrainch.fd)elserun_job(tcdrain_jobch.fd)externaltcflush_job:Unix.file_descr->Unix.flush_queue->unitjob="lwt_unix_tcflush_job"lettcflushchq=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcflushch.fdq)elserun_job(tcflush_jobch.fdq)externaltcflow_job:Unix.file_descr->Unix.flow_action->unitjob="lwt_unix_tcflow_job"lettcflowchact=check_descriptorch;ifSys.win32thenLwt.return(Unix.tcflowch.fdact)elserun_job(tcflow_jobch.fdact)(* +-----------------------------------------------------------------+
| Reading notifications |
+-----------------------------------------------------------------+ *)externalinit_notification:unit->Unix.file_descr="lwt_unix_init_notification"externalsend_notification:int->unit="lwt_unix_send_notification_stub"externalrecv_notifications:unit->intarray="lwt_unix_recv_notifications"lethandle_notifications_=(* Process available notifications. *)Array.itercall_notification(recv_notifications())letevent_notifications=ref(Lwt_engine.on_readable(init_notification())handle_notifications)(* +-----------------------------------------------------------------+
| Signals |
+-----------------------------------------------------------------+ *)externalset_signal:int->int->bool->unit="lwt_unix_set_signal"externalremove_signal:int->bool->unit="lwt_unix_remove_signal"externalinit_signals:unit->unit="lwt_unix_init_signals"externalhandle_signal:int->unit="lwt_unix_handle_signal"let()=init_signals()letset_signalsignumnotification=set_signalsignumnotification(Lwt_engine.forwards_signalsignum)letremove_signalsignum=remove_signalsignum(Lwt_engine.forwards_signalsignum)moduleSignal_map=Map.Make(structtypet=intletcompareab=a-bend)typesignal_handler={sh_num:int;sh_node:(signal_handler_id->int->unit)Lwt_sequence.node;}andsignal_handler_id=signal_handleroptionrefletsignals=refSignal_map.emptyletsignal_count()=Signal_map.fold(fun_signum(_id,actions)len->len+Lwt_sequence.lengthactions)!signals0leton_signal_fullsignumhandler=letid=refNoneinlet_,actions=trySignal_map.findsignum!signalswithNot_found->letactions=Lwt_sequence.create()inletnotification=make_notification(fun()->Lwt_sequence.iter_l(funf->fidsignum)actions)in(tryset_signalsignumnotificationwithexnwhenLwt.Exception_filter.runexn->stop_notificationnotification;raiseexn);signals:=Signal_map.addsignum(notification,actions)!signals;(notification,actions)inletnode=Lwt_sequence.add_rhandleractionsinid:=Some{sh_num=signum;sh_node=node};idleton_signalsignumf=on_signal_fullsignum(fun_idnum->fnum)letdisable_signal_handlerid=match!idwith|None->()|Somesh->id:=None;Lwt_sequence.removesh.sh_node;letnotification,actions=Signal_map.findsh.sh_num!signalsinifLwt_sequence.is_emptyactionsthenbeginremove_signalsh.sh_num;signals:=Signal_map.removesh.sh_num!signals;stop_notificationnotificationendletreinstall_signal_handlersignum=matchSignal_map.findsignum!signalswith|exceptionNot_found->()|notification,_->set_signalsignumnotification(* +-----------------------------------------------------------------+
| Processes |
+-----------------------------------------------------------------+ *)externalreset_after_fork:unit->unit="lwt_unix_reset_after_fork"letfork()=matchUnix.fork()with|0->(* Let the engine handle the fork *)Lwt_engine.fork();(* Reset threading. *)reset_after_fork();(* Stop the old event for notifications. *)Lwt_engine.stop_event!event_notifications;(* Reinitialise the notification system. *)event_notifications:=Lwt_engine.on_readable(init_notification())handle_notifications;(* Collect all pending jobs. *)letl=Lwt_sequence.fold_l(fun(_,f)l->f::l)jobs[]in(* Remove them all. *)Lwt_sequence.iter_node_lLwt_sequence.removejobs;(* And cancel them all. We yield first so that if the program
do an exec just after, it won't be executed. *)Lwt.on_termination(Lwt_main.yield()[@warning"-3"])(fun()->List.iter(funf->fLwt.Canceled)l);0|pid->pidtypeprocess_status=Unix.process_status=|WEXITEDofint|WSIGNALEDofint|WSTOPPEDofinttypewait_flag=Unix.wait_flag=|WNOHANG|WUNTRACEDtyperesource_usage={ru_utime:float;ru_stime:float}lethas_wait4=notSys.win32externalstub_wait4:Unix.wait_flaglist->int->int*Unix.process_status*resource_usage="lwt_unix_wait4"letdo_wait4flagspid=ifSys.win32||Lwt_config.androidthenletpid,status=Unix.waitpidflagspidin(pid,status,{ru_utime=0.0;ru_stime=0.0})elsestub_wait4flagspidletwait_children=Lwt_sequence.create()letwait_count()=Lwt_sequence.lengthwait_childrenletsigchld_handler_installed=reffalseletinstall_sigchld_handler()=ifnotSys.win32&¬!sigchld_handler_installedthenbeginsigchld_handler_installed:=true;ignorebeginon_signalSys.sigchld(fun_->Lwt_sequence.iter_node_lbeginfunnode->letwakener,flags,pid=Lwt_sequence.getnodeintrylet(pid',_,_)asv=do_wait4flagspidinifpid'<>0thenbeginLwt_sequence.removenode;Lwt.wakeupwakenervendwithewhenLwt.Exception_filter.rune->Lwt_sequence.removenode;Lwt.wakeup_exnwakenereendwait_children)endend(* The callback of Lwt.pause will only be run if Lwt_main.run is called by the
user. In that case, the process is positively using Lwt, and we want to
install the SIGCHLD handler, in order to cause any EINTR-unsafe code to
fail (as it should). *)let()=Lwt.async(fun()->Lwt.pause()>|=fun()->install_sigchld_handler())let_waitpidflagspid=Lwt.catch(fun()->Lwt.return(Unix.waitpidflagspid))Lwt.reraiseletwaitpid=ifSys.win32then_waitpidelsefunflagspid->install_sigchld_handler();ifList.memUnix.WNOHANGflagsthen_waitpidflagspidelseletflags=Unix.WNOHANG::flagsin_waitpidflagspid>>=fun((pid',_)asres)->ifpid'<>0thenLwt.returnreselsebeginlet(res,w)=Lwt.task()inletnode=Lwt_sequence.add_l(w,flags,pid)wait_childreninLwt.on_cancelres(fun_->Lwt_sequence.removenode);res>>=fun(pid,status,_)->Lwt.return(pid,status)endletwait4flagspid=install_sigchld_handler();ifSys.win32||Lwt_config.androidthenLwt.return(do_wait4flagspid)elseifList.memUnix.WNOHANGflagsthenLwt.return(do_wait4flagspid)elseletflags=Unix.WNOHANG::flagsinlet(pid',_,_)asres=do_wait4flagspidinifpid'<>0thenLwt.returnreselsebeginlet(res,w)=Lwt.task()inletnode=Lwt_sequence.add_l(w,flags,pid)wait_childreninLwt.on_cancelres(fun_->Lwt_sequence.removenode);resendletwait()=waitpid[](-1)externalsystem_job:string->intjob="lwt_unix_system_job"# 2447 "src/unix/lwt_unix.cppo.ml"externalunix_exit:int->'a="unix_exit"# 2450 "src/unix/lwt_unix.cppo.ml"letsystemcmd=ifSys.win32thenrun_job(system_job("cmd.exe /c "^cmd))>>=funcode->Lwt.return(Unix.WEXITEDcode)elsematchfork()with|0->begintryUnix.execv"/bin/sh"[|"/bin/sh";"-c";cmd|]with_->(* Do not run at_exit hooks *)unix_exit127end|id->waitpid[]id>|=snd(* +-----------------------------------------------------------------+
| Misc |
+-----------------------------------------------------------------+ *)letrun=Lwt_main.runlethandle_unix_errorfx=Lwt.catch(fun()->fx)(funexn->Unix.handle_unix_error(fun()->raiseexn)())(* +-----------------------------------------------------------------+
| System thread pool |
+-----------------------------------------------------------------+ *)[@@@ocaml.warning"-3"]externalpool_size:unit->int="lwt_unix_pool_size""noalloc"externalset_pool_size:int->unit="lwt_unix_set_pool_size""noalloc"externalthread_count:unit->int="lwt_unix_thread_count""noalloc"externalthread_waiting_count:unit->int="lwt_unix_thread_waiting_count""noalloc"[@@@ocaml.warning"+3"](* +-----------------------------------------------------------------+
| CPUs |
+-----------------------------------------------------------------+ *)externalget_cpu:unit->int="lwt_unix_get_cpu"externalstub_get_affinity:int->intlist="lwt_unix_get_affinity"externalstub_set_affinity:int->intlist->unit="lwt_unix_set_affinity"letget_affinity?(pid=0)()=stub_get_affinitypidletset_affinity?(pid=0)l=stub_set_affinitypidl(* +-----------------------------------------------------------------+
| Error printing |
+-----------------------------------------------------------------+ *)let()=Printexc.register_printer(function|Unix.Unix_error(error,func,arg)->leterror=matcherrorwith|Unix.E2BIG->"E2BIG"|Unix.EACCES->"EACCES"|Unix.EAGAIN->"EAGAIN"|Unix.EBADF->"EBADF"|Unix.EBUSY->"EBUSY"|Unix.ECHILD->"ECHILD"|Unix.EDEADLK->"EDEADLK"|Unix.EDOM->"EDOM"|Unix.EEXIST->"EEXIST"|Unix.EFAULT->"EFAULT"|Unix.EFBIG->"EFBIG"|Unix.EINTR->"EINTR"|Unix.EINVAL->"EINVAL"|Unix.EIO->"EIO"|Unix.EISDIR->"EISDIR"|Unix.EMFILE->"EMFILE"|Unix.EMLINK->"EMLINK"|Unix.ENAMETOOLONG->"ENAMETOOLONG"|Unix.ENFILE->"ENFILE"|Unix.ENODEV->"ENODEV"|Unix.ENOENT->"ENOENT"|Unix.ENOEXEC->"ENOEXEC"|Unix.ENOLCK->"ENOLCK"|Unix.ENOMEM->"ENOMEM"|Unix.ENOSPC->"ENOSPC"|Unix.ENOSYS->"ENOSYS"|Unix.ENOTDIR->"ENOTDIR"|Unix.ENOTEMPTY->"ENOTEMPTY"|Unix.ENOTTY->"ENOTTY"|Unix.ENXIO->"ENXIO"|Unix.EPERM->"EPERM"|Unix.EPIPE->"EPIPE"|Unix.ERANGE->"ERANGE"|Unix.EROFS->"EROFS"|Unix.ESPIPE->"ESPIPE"|Unix.ESRCH->"ESRCH"|Unix.EXDEV->"EXDEV"|Unix.EWOULDBLOCK->"EWOULDBLOCK"|Unix.EINPROGRESS->"EINPROGRESS"|Unix.EALREADY->"EALREADY"|Unix.ENOTSOCK->"ENOTSOCK"|Unix.EDESTADDRREQ->"EDESTADDRREQ"|Unix.EMSGSIZE->"EMSGSIZE"|Unix.EPROTOTYPE->"EPROTOTYPE"|Unix.ENOPROTOOPT->"ENOPROTOOPT"|Unix.EPROTONOSUPPORT->"EPROTONOSUPPORT"|Unix.ESOCKTNOSUPPORT->"ESOCKTNOSUPPORT"|Unix.EOPNOTSUPP->"EOPNOTSUPP"|Unix.EPFNOSUPPORT->"EPFNOSUPPORT"|Unix.EAFNOSUPPORT->"EAFNOSUPPORT"|Unix.EADDRINUSE->"EADDRINUSE"|Unix.EADDRNOTAVAIL->"EADDRNOTAVAIL"|Unix.ENETDOWN->"ENETDOWN"|Unix.ENETUNREACH->"ENETUNREACH"|Unix.ENETRESET->"ENETRESET"|Unix.ECONNABORTED->"ECONNABORTED"|Unix.ECONNRESET->"ECONNRESET"|Unix.ENOBUFS->"ENOBUFS"|Unix.EISCONN->"EISCONN"|Unix.ENOTCONN->"ENOTCONN"|Unix.ESHUTDOWN->"ESHUTDOWN"|Unix.ETOOMANYREFS->"ETOOMANYREFS"|Unix.ETIMEDOUT->"ETIMEDOUT"|Unix.ECONNREFUSED->"ECONNREFUSED"|Unix.EHOSTDOWN->"EHOSTDOWN"|Unix.EHOSTUNREACH->"EHOSTUNREACH"|Unix.ELOOP->"ELOOP"|Unix.EOVERFLOW->"EOVERFLOW"|Unix.EUNKNOWNERRn->Printf.sprintf"EUNKNOWNERR %d"ninSome(Printf.sprintf"Unix.Unix_error(Unix.%s, %S, %S)"errorfuncarg)|_->None)moduleVersioned=structletbind_1chaddr=check_descriptorch;Unix.bindch.fdaddrletbind_2=bindletrecv_msg_2=recv_msgletsend_msg_2=send_msgend