1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572# 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=matchtrySome(Notifiers.findnotifiersid)withNot_found->Nonewith|Somenotifier->ifnotifier.notify_oncethenstop_notificationid;notifier.notify_handler()|None->()(* +-----------------------------------------------------------------+
| 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_main.yieldletauto_yieldtimeout=letlimit=ref(Unix.gettimeofday()+.timeout)infun()->letcurrent=Unix.gettimeofday()inifcurrent>=!limitthenbeginlimit:=current+.timeout;yield();endelseLwt.return_unitexceptionTimeoutlettimeoutd=sleepd>>=fun()->Lwt.failTimeoutletwith_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)withexn->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_varletexecute_job?async_method~job~result~free=letasync_method=choose_async_methodasync_methodinrun_job_auxasync_methodjob(funjob->letx=wrap_resultresultjobinfreejob;x)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)withexn->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)withexn->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|e->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|e->Lwt.faile(* +-----------------------------------------------------------------+
| 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# 597 "src/unix/lwt_unix.cppo.ml"|O_KEEPEXEC# 600 "src/unix/lwt_unix.cppo.ml"externalopen_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.failexternalstub_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.failexternalstub_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->int="lwt_unix_iov_max"letsystem_limit=ifSys.win32thenNoneelseSome(stub_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.statname)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.faile)[@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.faile)[@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 |
+-----------------------------------------------------------------+ *)letdupch=check_descriptorch;letfd=Unix.dupch.fdin{fd=fd;state=Opened;set_flags=ch.set_flags;blocking=ifch.set_flagsthenlazy(Lazy.forcech.blocking>>=function|true->Unix.clear_nonblockfd;Lwt.return_true|false->Unix.set_nonblockfd;Lwt.return_false)elsech.blocking;event_readable=None;event_writable=None;hooks_readable=Lwt_sequence.create();hooks_writable=Lwt_sequence.create();}letdup2ch1ch2=check_descriptorch1;Unix.dup2ch1.fdch2.fd;ch2.set_flags<-ch1.set_flags;ch2.blocking<-(ifch2.set_flagsthenlazy(Lazy.forcech1.blocking>>=function|true->Unix.clear_nonblockch2.fd;Lwt.return_true|false->Unix.set_nonblockch2.fd;Lwt.return_false)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.returnarrayelsematchtryarray.(i)<-Unix.readdirhandle;truewithEnd_of_file->falsewith|true->fill(i+1)|false->Lwt.return(Array.subarray0i)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.failexn)>>=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.failexn)>>=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()=let(out_fd,in_fd)=Unix.pipe()in(mk_ch~blocking:Sys.win32out_fd,mk_ch~blocking:Sys.win32in_fd)letpipe_in()=let(out_fd,in_fd)=Unix.pipe()in(mk_ch~blocking:Sys.win32out_fd,in_fd)letpipe_out()=let(out_fd,in_fd)=Unix.pipe()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"letsymlinkname1name2=ifSys.win32thenLwt.return(Unix.symlinkname1name2)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->int="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_countfds)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*intletsocketdomtypproto=lets=Unix.socketdomtypprotoinmk_ch~blocking:falsestypeshutdown_command=Unix.shutdown_command=|SHUTDOWN_RECEIVE|SHUTDOWN_SEND|SHUTDOWN_ALLletshutdownchshutdown_command=check_descriptorch;Unix.shutdownch.fdshutdown_commandexternalstub_socketpair:socket_domain->socket_type->int->Unix.file_descr*Unix.file_descr="lwt_unix_socketpair_stub"letsocketpairdomtypproto=# 1675 "src/unix/lwt_unix.cppo.ml"letdo_socketpair=ifSys.win32thenstub_socketpairelseUnix.socketpair?cloexec:Nonein# 1681 "src/unix/lwt_unix.cppo.ml"let(s1,s2)=do_socketpairdomtypprotoin(mk_ch~blocking:falses1,mk_ch~blocking:falses2)externalaccept4:close_on_exec:bool->nonblock:bool->Unix.file_descr->Unix.file_descr*Unix.sockaddr="lwt_unix_accept4"letaccept_and_set_nonblockch_fd=ifLwt_config._HAVE_ACCEPT4thenlet(fd,addr)=accept4~close_on_exec:false~nonblock:truech_fdin(mk_ch~blocking:false~set_flags:falsefd,addr)elselet(fd,addr)=Unix.acceptch_fdin(mk_ch~blocking:falsefd,addr)letacceptch=wrap_syscallReadch(fun_->accept_and_set_nonblockch.fd)letaccept_nchn=letl=ref[]inLazy.forcech.blocking>>=funblocking->Lwt.catch(fun()->wrap_syscallReadchbeginfun()->begintryfor_i=1tondoifblocking&¬(unix_readablech.fd)thenraiseRetry;l:=accept_and_set_nonblockch.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_ONLYtypesocket_int_option=Unix.socket_int_option=|SO_SNDBUF|SO_RCVBUF|SO_ERROR|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->unit="lwt_unix_set_signal"externalremove_signal:int->unit="lwt_unix_remove_signal"externalinit_signals:unit->unit="lwt_unix_init_signals"let()=init_signals()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_signalsignumnotificationwithexn->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=matchtrySome(Signal_map.findsignum!signals)withNot_found->Nonewith|Some(notification,_)->set_signalsignumnotification|None->()(* +-----------------------------------------------------------------+
| Processes |
+-----------------------------------------------------------------+ *)externalreset_after_fork:unit->unit="lwt_unix_reset_after_fork"letfork()=matchUnix.fork()with|0->(* 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())(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.wakeupwakenervendwithe->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.failletwaitpid=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"externalunix_exit:int->'a="unix_exit"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