123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105(**************************************************************************)(* This file is part of BINSEC. *)(* *)(* Copyright (C) 2016-2026 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)externalset_pdeathsig:int->int="caml_subprocess_set_pdeathsig""native_subprocess_set_pdeathsig"[@@untagged][@@noalloc]lethandle_pdeathsig=function|None->()|Somesignal->ifset_pdeathsigsignal=-1thenUnix.kill(Unix.getpid())Sys.sigkilltypet={mutablevalid:bool;pid:int;stdin:out_channel;stdout:in_channel;stderr:in_channel;}openUnixletspawn?pdeathsigargs=letinr,inw=pipe~cloexec:true()inletoutr,outw=trypipe~cloexec:true()withe->closeinr;closeinw;raiseeinleterrr,errw=trypipe~cloexec:true()withe->closeinr;closeinw;closeoutr;closeoutw;raiseeinmatchfork()with|0->(* in child *)dup2~cloexec:falseinrUnix.stdin;dup2~cloexec:falseoutwUnix.stdout;dup2~cloexec:falseerrwUnix.stderr;handle_pdeathsigpdeathsig;execvpargs.(0)args|pid->closeinr;closeoutw;closeerrw;{valid=true;pid;stdin=out_channel_of_descrinw;stdout=in_channel_of_descroutr;stderr=in_channel_of_descrerrr;}|exceptione->closeinr;closeinw;closeoutr;closeoutw;closeerrr;closeerrw;raiseeletrecwaitpid_non_intrpid=trywaitpid[]pidwithUnix_error(EINTR,_,_)->waitpid_non_intrpidletpleasefx=tryfxwithSys_error_|Unix_error_->()letcloset=ift.valid=falsethenraise(Invalid_argument"process has already been closed");t.valid<-false;pleaseclose_outt.stdin;pleaseclose_int.stdout;pleaseclose_int.stderr;(trykillt.pidSys.sigkillwithUnix_error(ESRCH,"kill",_)->());snd(waitpid_non_intrt.pid)letpid{pid;_}=pidletstdin{stdin;_}=stdinletstdout{stdout;_}=stdoutletstderr{stderr;_}=stderr