unit signal; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface const _SIG_WORDS =4; _SIG_MAXSIG =128; const SIG_BLOCK =1; SIG_UNBLOCK =2; SIG_SETMASK =3; SIGPROCMASK_OLD =$0001; SIGPROCMASK_PROC_LOCKED =$0002; SIGPROCMASK_PS_LOCKED =$0004; SIGPROCMASK_FASTBLK =$0008; const SIGHUP =1; // hangup SIGINT =2; // interrupt SIGQUIT =3; // quit SIGILL =4; // illegal instr. (not reset when caught) SIGTRAP =5; // trace trap (not reset when caught) SIGABRT =6; // abort() SIGIOT =SIGABRT; // compatibility SIGEMT =7; // EMT instruction SIGFPE =8; // floating point exception SIGKILL =9; // kill (cannot be caught or ignored) SIGBUS =10; // bus error SIGSEGV =11; // segmentation violation SIGSYS =12; // non-existent system call invoked SIGPIPE =13; // write on a pipe with no one to read it SIGALRM =14; // alarm clock SIGTERM =15; // software termination signal from kill SIGURG =16; // urgent condition on IO channel SIGSTOP =17; // sendable stop signal not from tty SIGTSTP =18; // stop signal from tty SIGCONT =19; // continue a stopped process SIGCHLD =20; // to parent on child stop or exit SIGTTIN =21; // to readers pgrp upon background tty read SIGTTOU =22; // like TTIN if (tp->t_local<OSTOP) SIGIO =23; // input/output possible signal SIGXCPU =24; // exceeded CPU time limit SIGXFSZ =25; // exceeded file size limit SIGVTALRM=26; // virtual time alarm SIGPROF =27; // profiling time alarm SIGWINCH =28; // window size changes SIGINFO =29; // information request SIGUSR1 =30; // user defined signal 1 SIGUSR2 =31; // user defined signal 2 SIGTHR =32; // reserved by thread library. SIGLWP =SIGTHR; SIGCANCEL=SIGTHR; NSIG=32; SIGRTMIN=65; SIGRTMAX=126; SIG_DFL = 0; //default SIG_IGN = 1; //ignore SIG_ERR =-1; SIG_CATCH= 2; //See signalvar.h SIG_HOLD = 3; SA_ONSTACK =$0001; // take signal on signal stack SA_RESTART =$0002; // restart system call on signal return SA_RESETHAND =$0004; // reset to SIG_DFL when taking signal SA_NODEFER =$0010; // don't mask the signal we're delivering SA_NOCLDWAIT =$0020; // don't keep zombies around SA_SIGINFO =$0040; // signal handler with SA_SIGINFO args SI_NOINFO =0; // No signal info besides si_signo. SI_USER =$10001; // Signal sent by kill(). SI_QUEUE =$10002; // Signal sent by the sigqueue(). SI_TIMER =$10003; // Signal generated by expiration of a timer set by timer_settime(). SI_ASYNCIO=$10004; // Signal generated by completion of an asynchronous I/O request. SI_MESGQ =$10005; // Signal generated by arrival of a message on an empty message queue. SI_KERNEL =$10006; SI_LWP =$10007; // Signal sent by thr_kill //mc_fpformat _MC_FPFMT_NODEV=$10000; // device not present or configured _MC_FPFMT_XMM =$10002; //mc_ownedfp _MC_FPOWNED_NONE=$20000; // FP state not used _MC_FPOWNED_FPU =$20001; // FP state came from FPU _MC_FPOWNED_PCB =$20002; // FP state came from PCB //mc_flags bits. Shall be in sync with TF_XXX. _MC_HASSEGS =$1; //mc_ds,mc_es,mc_fs,mc_gs _MC_HASBASES =$2; //mc_fsbase,mc_gsbase _MC_HASFPXSTATE=$4; //xmm _MC_FLAG_MASK =(_MC_HASSEGS or _MC_HASBASES or _MC_HASFPXSTATE); TF_HASSEGS =$1; TF_HASBASES =$2; TF_HASFPXSTATE=$4; type p_sigset_t=^sigset_t; sigset_t=packed record //16 Case Byte of 0:(bits:array[0.._SIG_WORDS-1] of DWORD); 1:(qwords:array[0..(_SIG_WORDS div 2)-1] of QWORD); end; {$IF sizeof(sigset_t)<>16}{$STOP sizeof(sigset_t)<>16}{$ENDIF} sigval=packed record //8 Case Byte of // Members as suggested by Annex C of POSIX 1003.1b. 0:(sival_int:Integer); 1:(sival_ptr:Pointer); //6.0 compatibility 2:(sigval_int:Integer); 3:(sigval_ptr:Pointer); end; {$IF sizeof(sigval)<>8}{$STOP sizeof(sigval)<>8}{$ENDIF} p_sigevent=^sigevent; sigevent=packed record sigev_notify:Integer; //Notification type sigev_signo :Integer; //Signal number sigev_value :sigval; //Signal value _sigev_un:packed record Case Byte of 0:(_threadid:Integer); //__lwpid_t 1:(_sigev_thread:packed record _function :Pointer; //void (*_function)(union sigval); _attribute:Pointer; //pthread_attr_t end); 2:(__spare__:array[0..7] of QWORD); end; end; p_siginfo_t=^siginfo_t; siginfo_t=packed record //80 si_signo:Integer; //signal number si_errno:Integer; //errno association { * Cause of signal, one of the SI_ macros or signal-specific * values, i.e. one of the FPE_... values for SIGFPE. This * value is equivalent to the second argument to an old-style * FreeBSD signal handler. } si_code :Integer; // signal code SI_USER si_pid :Integer; // sending process si_uid :DWORD; // sender's ruid si_status:Integer; // exit value si_addr :Pointer; // faulting instruction si_value :sigval; // signal value _reason:packed record Case Byte of 0:(_fault:packed record _trapno:Integer; // machine specific trap code end); 1:(_timer:packed record _timerid:Integer; _overrun:Integer; end); 2:(_mesgq:packed record _mqd:Integer; end); 3:(_poll:packed record _band:QWORD; // band event for SIGPOLL end); 4:(__spare__:packed record __spare1__:QWORD; __spare2__:array[0..7] of Integer; end); end; end; {$IF sizeof(siginfo_t)<>80}{$STOP sizeof(siginfo_t)<>80}{$ENDIF} sa_handler =procedure(sig,code:Integer;ctx:Pointer); SysV_ABI_CDecl; sa_sigaction=procedure(sig:Integer;info:p_siginfo_t;ctx:Pointer); SysV_ABI_CDecl; sig_t=sa_handler; p_sigaction_t=^sigaction_t; sigaction_t=packed record //28 u:packed record // signal handler Case Byte of 0:(code:Ptrint); //SIG_DFL 1:(sa_handler:sa_handler); //void (*__sa_handler)(int); 2:(sa_sigaction:sa_sigaction); //void (*__sa_sigaction)(int, struct __siginfo *, void *); (sa_flags and SA_SIGINFO)<>0 end; sa_flags:Integer; //SA_SIGINFO sa_mask :sigset_t; //signal mask to apply (signal mask inside signal) end; {$IF sizeof(sigaction_t)<>28}{$STOP sizeof(sigaction_t)<>28}{$ENDIF} sigaltstack=packed record ss_sp :Pointer; //signal stack base ss_size :size_t; //signal stack length SIGSTKSZ ss_flags:Integer; //SS_DISABLE and/or SS_ONSTACK _align :Integer; end; p_stack_t=^stack_t; stack_t=sigaltstack; {$IF sizeof(stack_t)<>24}{$STOP sizeof(stack_t)<>24}{$ENDIF} const SA_NOCLDSTOP=$0008; // do not generate SIGCHLD on child stop SS_ONSTACK =$0001; // take signal on alternate stack SS_DISABLE =$0004; // disable taking signals on alternate stack MINSIGSTKSZ =(512*4); // minimum stack size SIGSTKSZ =(MINSIGSTKSZ+32768); // recommended stack size // uc_flags _UC_SIGMASK=$01; // valid uc_sigmask _UC_STACK =$02; // valid uc_stack _UC_CPU =$04; // valid GPR context in uc_mcontext _UC_FPU =$08; // valid FPU context in uc_mcontext function _SIG_IDX(sig:Integer):DWORD; inline; function _SIG_VALID(sig:Integer):Boolean; inline; function _SIG_VALID_32(sig:Integer):Boolean; inline; function _SIG_WORD(sig:Integer):DWORD; inline; function _SIG_BIT(sig:Integer):DWORD; inline; procedure ps_mtx_lock; external; procedure ps_mtx_unlock; external; function sigdeferstop:Integer; external; procedure sigallowstop; external; Function sigonstack(sp:size_t):Integer; external; Function cursig(td:Pointer;stop_allowed:Integer):Integer; external; procedure tdsignal(td:Pointer;sig:Integer); external; procedure sigexit(td:Pointer;sig:Integer); external; procedure ast; external; Function kern_sigprocmask(td:Pointer; how:Integer; _set:p_sigset_t; oset:p_sigset_t; flags:Integer ):Integer; external; function _get_sig_str(signum:Integer):RawByteString; implementation function _SIG_IDX(sig:Integer):DWORD; inline; begin Result:=sig-1; end; function _SIG_VALID(sig:Integer):Boolean; inline; begin Result:=(sig<=_SIG_MAXSIG) and (sig>0); end; function _SIG_VALID_32(sig:Integer):Boolean; inline; begin Result:=(sig<=32) and (sig>0); end; function _SIG_WORD(sig:Integer):DWORD; inline; begin Result:=_SIG_IDX(sig) shr 5; end; function _SIG_BIT(sig:Integer):DWORD; inline; begin Result:=1 shl (_SIG_IDX(sig) and 31); end; function _get_sig_str(signum:Integer):RawByteString; begin case signum of SIGHUP :Result:='SIGHUP'; SIGINT :Result:='SIGINT'; SIGQUIT :Result:='SIGQUIT'; SIGILL :Result:='SIGILL'; SIGTRAP :Result:='SIGTRAP'; SIGABRT :Result:='SIGABRT'; SIGEMT :Result:='SIGEMT'; SIGFPE :Result:='SIGFPE'; SIGKILL :Result:='SIGKILL'; SIGBUS :Result:='SIGBUS'; SIGSEGV :Result:='SIGSEGV'; SIGSYS :Result:='SIGSYS'; SIGPIPE :Result:='SIGPIPE'; SIGALRM :Result:='SIGALRM'; SIGTERM :Result:='SIGTERM'; SIGURG :Result:='SIGURG'; SIGSTOP :Result:='SIGSTOP'; SIGTSTP :Result:='SIGTSTP'; SIGCONT :Result:='SIGCONT'; SIGCHLD :Result:='SIGCHLD'; SIGTTIN :Result:='SIGTTIN'; SIGTTOU :Result:='SIGTTOU'; SIGIO :Result:='SIGIO'; SIGXCPU :Result:='SIGXCPU'; SIGXFSZ :Result:='SIGXFSZ'; SIGVTALRM:Result:='SIGVTALRM'; SIGPROF :Result:='SIGPROF'; SIGWINCH :Result:='SIGWINCH'; SIGINFO :Result:='SIGINFO'; SIGUSR1 :Result:='SIGUSR1'; SIGUSR2 :Result:='SIGUSR2'; SIGTHR :Result:='SIGTHR'; else Str(signum,Result); end; end; end.