3 {signal code by plugwash}
\r 
   5 { Copyright (C) 2005 Bas Steendijk and Peter Green
\r 
   6   For conditions of distribution and use, see copyright notice in zlib_license.txt
\r 
   7   which is included in the package
\r 
   8   ----------------------------------------------------------------------------- }
\r 
  17       baseunix,unix,unixutil,sockets,
\r 
  19     classes,lcore,lloopback;
\r 
  22     tsignalevent=procedure(sender:tobject;signal:integer) of object;
\r 
  23     tlsignal=class(tcomponent)
\r 
  25       onsignal           : tsignalevent      ;
\r 
  26       prevsignal         : tlsignal          ;
\r 
  27       nextsignal         : tlsignal          ;
\r 
  29       constructor create(aowner:tcomponent);override;
\r 
  30       destructor destroy;override;
\r 
  34   procedure starthandlesignal(signal:integer);
\r 
  37   firstsignal : tlsignal;
\r 
  39   signalloopback                        : tlloopback ;
\r 
  42 {$include unixstuff.inc}
\r 
  44 constructor tlsignal.create;
\r 
  46   inherited create(AOwner);
\r 
  47   nextsignal := firstsignal;
\r 
  50   if assigned(nextsignal) then nextsignal.prevsignal := self;
\r 
  51   firstsignal := self;
\r 
  55   //released := false;
\r 
  58 destructor tlsignal.destroy;
\r 
  60   if prevsignal <> nil then begin
\r 
  61     prevsignal.nextsignal := nextsignal;
\r 
  63     firstsignal := nextsignal;
\r 
  65   if nextsignal <> nil then begin
\r 
  66     nextsignal.prevsignal := prevsignal;
\r 
  72     {$define needsignalworkaround}
\r 
  75     {$define needsignalworkaround}
\r 
  78     {$define needsignalworkaround}
\r 
  81 {$ifdef needsignalworkaround}
\r 
  82   //using the 1.9.6 version of this stuff because the 1.9.8 and 2.0.0 versions seem broken
\r 
  84     TSysParam  = Longint;
\r 
  85     TSysResult = longint;
\r 
  87             syscall_nr_sigaction                = 67;
\r 
  88   //function Do_SysCall(sysnr:TSysParam):TSysResult;  {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL0';
\r 
  89   //function Do_SysCall(sysnr,param1:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL1';
\r 
  90   //function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult;  {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL2';
\r 
  91   function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL3';
\r 
  92   //function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL4';
\r 
  93   //function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult;  {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL5';
\r 
  95   function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint;// [public, alias : 'FPC_SYSC_SIGACTION'];
\r 
  97     Change action of process upon receipt of a signal.
\r 
  98     Signum specifies the signal (all except SigKill and SigStop).
\r 
  99     If Act is non-nil, it is used to specify the new action.
\r 
 100     If OldAct is non-nil the previous action is saved there.
\r 
 103   //writeln('fucking');
\r 
 104   {$ifdef RTSIGACTION}
\r 
 106       { Sparc has an extra stub parameter }
\r 
 107       Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(PtrInt(@Fprt_sigreturn_stub)-8),TSysParam(8));
\r 
 109       Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(8));
\r 
 111   {$else RTSIGACTION}
\r 
 113     Fpsigaction:=do_syscall(syscall_nr_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact));
\r 
 114   {$endif RTSIGACTION}
\r 
 118 // cdecl procedures are not name mangled
\r 
 119 // so USING something unlikely to cause collisions in the global namespace
\r 
 121 procedure lsignal_handler( Sig : Integer);cdecl;
\r 
 123   currentsignal : tlsignal;
\r 
 125 //  writeln('in lsignal_handler');
\r 
 126   currentsignal := firstsignal;
\r 
 127   while assigned(currentsignal) do begin
\r 
 128     if assigned(currentsignal.onsignal) then currentsignal.onsignal(currentsignal,sig);
\r 
 129     currentsignal := currentsignal.nextsignal;
\r 
 132 //  writeln('about to send down signalloopback');
\r 
 133   if assigned(signalloopback) then begin
\r 
 134     signalloopback.sendstr(' ');
\r 
 136 //  writeln('left lsignal_handler');
\r 
 141 {$if (FPC_VERSION > 2) or ((FPC_VERSION = 2) and (FPC_RELEASE >= 2))}
\r 
 142 procedure lsignal_handler2(signal:longint;info:PSigInfo;context:psigcontext); cdecl;
\r 
 144 procedure lsignal_handler2(signal:longint;var info:TSigInfo_t;var context:SigContextRec); cdecl;
\r 
 148   lsignal_handler(signal);
\r 
 156     saction : sigactionrec = (handler:(sh:lsignal_handler);sa_flags:0);
\r 
 159       saction : sigactionrec = (sa_handler:sigactionhandler(lsignal_handler);sa_flags:0);
\r 
 162         //version number is FPC_VERSION.FPC_RELEASE.FPC_PATCH
\r 
 163         {$if (FPC_VERSION>2) or ((FPC_VERSION=2) and (FPC_RELEASE>0)) or ((FPC_VERSION=2) and (fpc_release=0) and (fpc_patch>=2))}
\r 
 164           saction : sigactionrec = (sa_handler:lsignal_handler2;sa_flags:0);
\r 
 166           saction : sigactionrec = (sa_handler:tsigaction(lsignal_handler);sa_flags:0);
\r 
 171           saction : sigactionrec = (handler:(sh:lsignal_handler);sa_flags:0);
\r 
 173           //version number is FPC_VERSION.FPC_RELEASE.FPC_PATCH
\r 
 174           {$if (FPC_VERSION>2) or ((FPC_VERSION=2) and (FPC_RELEASE>0)) or ((FPC_VERSION=2) and (fpc_release=0) and (fpc_patch>=2))}
\r 
 175             saction : sigactionrec = (sa_handler:{$ifndef ver1_9_6}{$ifndef ver1_9_4}{$ifndef ver1_0}SigActionHandler{$endif}{$endif}{$endif}(lsignal_handler);sa_flags:0;sa_restorer:nil);
\r 
 177             saction : sigactionrec = (sa_handler:{$ifndef ver1_9_6}{$ifndef ver1_9_4}{$ifndef ver1_0}SigActionHandler{$endif}{$endif}{$endif}(lsignal_handler));
\r 
 183 procedure starthandlesignal(signal:integer);
\r 
 185   if signal in ([0..31]-[sigkill,sigstop]) then begin
\r 
 186     sigprocmask(SIG_BLOCK,@blockset,nil);
\r 
 187     sigaction(signal,@saction,nil)
\r 
 189     raise exception.create('invalid signal number')
\r 
 194   fillchar(blockset,sizeof(blockset),0);
\r 
 195   blockset[0] := $FFFFFFFF - (1 shl sigstop) - (1 shl sigkill) - (1 shl sigsegv);
\r 
 197     saction.sa_mask := blockset[0];
\r 
 199     saction.sa_mask := blockset;
\r