unit kern_exit; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses sys_resource; const WCOREFLAG=&0200; _WSTOPPED=&0177; { _WSTATUS if process is stopped } { * Option bits for the third argument of wait4. WNOHANG causes the * wait to not hang if there are no stopped or terminated processes, rather * returning an error indication in this case (pid==0). WUNTRACED * indicates that the caller should receive status about untraced children * which stop due to signals. If children are stopped and a wait without * this option is done, it is as though they were still running... nothing * about them is returned. WNOWAIT only request information about zombie, * leaving the proc around, available for later waits. } WNOHANG =1; { Don't hang in wait. } WUNTRACED =2; { Tell about stopped, untraced children. } WSTOPPED =WUNTRACED; { SUS compatibility } WCONTINUED=4; { Report a job control continued process. } WNOWAIT =8; { Poll only. Don't delete the proc entry. } WEXITED =16; { Wait for exited processes. } WTRAPPED =32; { Wait for a process to hit a trap or a breakpoint. } WLINUXCLONE=$80000000; { Wait for kthread spawned from linux_clone. } { * Tokens for special values of the "pid" parameter to wait4. * Extended struct __wrusage to collect rusage for both the target * process and its children within one wait6() call. } WAIT_ANY =(-1); { any process } WAIT_MYPGRP=0; { any process in my process group } type _W_INT=Integer; function _WSTATUS(x:Integer):Integer; inline; function WIFSTOPPED(x:Integer):Boolean; inline; function WSTOPSIG(x:Integer):Integer; inline; function WIFSIGNALED(x:Integer):Boolean; inline; function WTERMSIG(x:Integer):Integer; inline; function WIFEXITED(x:Integer):Boolean; inline; function WEXITSTATUS(x:Integer):Integer; inline; function WIFCONTINUED(x:Integer):Boolean; inline; { 0x13=SIGCONT } function WCOREDUMP(x:Integer):Boolean; inline; function W_STOPCODE(sig:Integer):Integer; inline; function W_EXITCODE(ret,sig:Integer):Integer; inline; procedure exit1(rv:Integer); procedure sys_sys_exit(rval:Integer); function sys_wait4(pid:Integer;status:PInteger;options:Integer;rusage:Pointer):Integer; implementation uses errno, systm, sys_bootparam, kern_proc, sys_event, md_sleep, md_proc; function _WSTATUS(x:Integer):Integer; inline; begin Result:=(_W_INT(x) and &0177); end; function WIFSTOPPED(x:Integer):Boolean; inline; begin Result:=(_WSTATUS(x)=_WSTOPPED); end; function WSTOPSIG(x:Integer):Integer; inline; begin Result:=(_W_INT(x) shr 8) ; end; function WIFSIGNALED(x:Integer):Boolean; inline; begin Result:=(_WSTATUS(x)<>_WSTOPPED) and (_WSTATUS(x)<>0); end; function WTERMSIG(x:Integer):Integer; inline; begin Result:=(_WSTATUS(x)); end; function WIFEXITED(x:Integer):Boolean; inline; begin Result:=(_WSTATUS(x)=0); end; function WEXITSTATUS(x:Integer):Integer; inline; begin Result:=(_W_INT(x) shr 8); end; function WIFCONTINUED(x:Integer):Boolean; inline; { 0x13=SIGCONT } begin Result:=(x=$13); end; function WCOREDUMP(x:Integer):Boolean; inline; begin Result:=(_W_INT(x) and WCOREFLAG)<>0; end; function W_STOPCODE(sig:Integer):Integer; inline; begin Result:=(sig shl 8) or _WSTOPPED; end; function W_EXITCODE(ret,sig:Integer):Integer; inline; begin Result:=(ret shl 8) or sig; end; procedure thread_suspend_all(exclude:Pointer); external; procedure exit1(rv:Integer); begin //Notify interested parties of our demise. KNOTE_UNLOCKED(@p_proc.p_klist, NOTE_EXIT); // if (p_halt_on_exit) then begin md_halt(rv); end else begin thread_suspend_all(p_host_ipc_td); msleep_td(0); end; end; procedure sys_sys_exit(rval:Integer); begin exit1(W_EXITCODE(rval, 0)); // NOTREACHED end; function kern_wait(pid:Integer;status:PInteger;options:Integer;rusage:p_rusage):Integer; begin options:=options or WEXITED or WTRAPPED; { If we don't know the option, just return. } if ((options and (not (WUNTRACED or WNOHANG or WCONTINUED or WNOWAIT or WEXITED or WTRAPPED or WLINUXCLONE)))<>0) then begin Exit(EINVAL); end; if ((options and (WEXITED or WUNTRACED or WCONTINUED or WTRAPPED))=0) then begin { * We will be unable to find any matching processes, * because there are no known events to look for. * Prefer to Exiterror instead of blocking * indefinitely. } Exit(EINVAL); end; Exit(ECHILD); end; { * The dirty work is handled by kern_wait(). } function sys_wait4(pid:Integer;status:PInteger;options:Integer;rusage:Pointer):Integer; var ru:t_rusage; rup:p_rusage; error,_status:Integer; begin if (rusage<>nil) then rup:=@ru else rup:=nil; error:=kern_wait(pid, @_status, options, rup); if (status<>nil) and (error=0) then error:=copyout(@_status, status, sizeof(_status)); if (rusage<>nil) and (error=0) then error:=copyout(@ru, rusage, sizeof(t_rusage)); Exit(error); end; end.