You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lsignal.pas 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. {lsocket.pas}
  2. {signal code by plugwash}
  3. { Copyright (C) 2005 Bas Steendijk and Peter Green
  4. For conditions of distribution and use, see copyright notice in zlib_license.txt
  5. which is included in the package
  6. ----------------------------------------------------------------------------- }
  7. unit lsignal;
  8. {$mode delphi}
  9. interface
  10. uses sysutils,
  11. {$ifdef VER1_0}
  12. linux,
  13. {$else}
  14. baseunix,unix,unixutil,
  15. {$endif}
  16. classes,lcore,lloopback;
  17. type
  18. tsignalevent=procedure(sender:tobject;signal:integer) of object;
  19. tlsignal=class(tcomponent)
  20. public
  21. onsignal : tsignalevent ;
  22. prevsignal : tlsignal ;
  23. nextsignal : tlsignal ;
  24. constructor create(aowner:tcomponent);override;
  25. destructor destroy;override;
  26. end;
  27. procedure starthandlesignal(signal:integer);
  28. var
  29. firstsignal : tlsignal;
  30. blockset : sigset;
  31. signalloopback : tlloopback ;
  32. implementation
  33. {$include unixstuff.inc}
  34. constructor tlsignal.create;
  35. begin
  36. inherited create(AOwner);
  37. nextsignal := firstsignal;
  38. prevsignal := nil;
  39. if assigned(nextsignal) then nextsignal.prevsignal := self;
  40. firstsignal := self;
  41. //interval := 1000;
  42. //enabled := true;
  43. //released := false;
  44. end;
  45. destructor tlsignal.destroy;
  46. begin
  47. if prevsignal <> nil then begin
  48. prevsignal.nextsignal := nextsignal;
  49. end else begin
  50. firstsignal := nextsignal;
  51. end;
  52. if nextsignal <> nil then begin
  53. nextsignal.prevsignal := prevsignal;
  54. end;
  55. inherited destroy;
  56. end;
  57. {$ifdef linux}
  58. {$ifdef ver1_9_8}
  59. {$define needsignalworkaround}
  60. {$endif}
  61. {$ifdef ver2_0_0}
  62. {$define needsignalworkaround}
  63. {$endif}
  64. {$ifdef ver2_0_2}
  65. {$define needsignalworkaround}
  66. {$endif}
  67. {$endif}
  68. {$ifdef needsignalworkaround}
  69. //using the 1.9.6 version of this stuff because the 1.9.8 and 2.0.0 versions seem broken
  70. type
  71. TSysParam = Longint;
  72. TSysResult = longint;
  73. const
  74. syscall_nr_sigaction = 67;
  75. //function Do_SysCall(sysnr:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL0';
  76. //function Do_SysCall(sysnr,param1:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL1';
  77. //function Do_SysCall(sysnr,param1,param2:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL2';
  78. function Do_SysCall(sysnr,param1,param2,param3:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL3';
  79. //function Do_SysCall(sysnr,param1,param2,param3,param4:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL4';
  80. //function Do_SysCall(sysnr,param1,param2,param3,param4,param5:TSysParam):TSysResult; {$ifndef VER1_0} oldfpccall; {$endif} external name 'FPC_SYSCALL5';
  81. function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint;// [public, alias : 'FPC_SYSC_SIGACTION'];
  82. {
  83. Change action of process upon receipt of a signal.
  84. Signum specifies the signal (all except SigKill and SigStop).
  85. If Act is non-nil, it is used to specify the new action.
  86. If OldAct is non-nil the previous action is saved there.
  87. }
  88. begin
  89. //writeln('fucking');
  90. {$ifdef RTSIGACTION}
  91. {$ifdef cpusparc}
  92. { Sparc has an extra stub parameter }
  93. Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(PtrInt(@Fprt_sigreturn_stub)-8),TSysParam(8));
  94. {$else cpusparc}
  95. Fpsigaction:=do_syscall(syscall_nr_rt_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact),TSysParam(8));
  96. {$endif cpusparc}
  97. {$else RTSIGACTION}
  98. //writeln('nice');
  99. Fpsigaction:=do_syscall(syscall_nr_sigaction,TSysParam(sig),TSysParam(act),TSysParam(oact));
  100. {$endif RTSIGACTION}
  101. end;
  102. {$endif}
  103. // cdecl procedures are not name mangled
  104. // so USING something unlikely to cause colliesions in the global namespace
  105. // is a good idea
  106. procedure lsignal_handler( Sig : Integer);cdecl;
  107. var
  108. currentsignal : tlsignal;
  109. begin
  110. // writeln('in lsignal_hanler');
  111. currentsignal := firstsignal;
  112. while assigned(currentsignal) do begin
  113. if assigned(currentsignal.onsignal) then currentsignal.onsignal(currentsignal,sig);
  114. currentsignal := currentsignal.nextsignal;
  115. end;
  116. // writeln('about to send down signalloopback');
  117. if assigned(signalloopback) then begin
  118. signalloopback.sendstr(' ');
  119. end;
  120. // writeln('left lsignal_hanler');
  121. end;
  122. {$ifdef freebsd}
  123. {$if (FPC_VERSION > 2) or ((FPC_VERSION = 2) and (FPC_RELEASE >= 2))}
  124. procedure lsignal_handler2(signal:longint;info:PSigInfo;context:psigcontext); cdecl;
  125. {$else}
  126. procedure lsignal_handler2(signal:longint;var info:TSigInfo_t;var context:SigContextRec); cdecl;
  127. {$endif}
  128. begin
  129. lsignal_handler(signal);
  130. end;
  131. {$endif}
  132. const
  133. allbitsset=-1;
  134. {$ifdef ver1_0}
  135. saction : sigactionrec = (handler:(sh:lsignal_handler);sa_flags:0);
  136. {$else}
  137. {$ifdef darwin}
  138. saction : sigactionrec = (sa_handler:tsigaction(lsignal_handler);sa_flags:0);
  139. {$else}
  140. {$ifdef freebsd}
  141. //version number is FPC_VERSION.FPC_RELEASE.FPC_PATCH
  142. {$if (FPC_VERSION>2) or ((FPC_VERSION=2) and (FPC_RELEASE>0)) or ((FPC_VERSION=2) and (fpc_release=0) and (fpc_patch>=2))}
  143. saction : sigactionrec = (sa_handler:lsignal_handler2;sa_flags:0);
  144. {$else}
  145. saction : sigactionrec = (sa_handler:tsigaction(lsignal_handler);sa_flags:0);
  146. {$endif}
  147. {$else}
  148. {$ifdef ver1_9_2}
  149. saction : sigactionrec = (handler:(sh:lsignal_handler);sa_flags:0);
  150. {$else}
  151. //version number is FPC_VERSION.FPC_RELEASE.FPC_PATCH
  152. {$if (FPC_VERSION>2) or ((FPC_VERSION=2) and (FPC_RELEASE>0)) or ((FPC_VERSION=2) and (fpc_release=0) and (fpc_patch>=2))}
  153. 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);
  154. {$else}
  155. saction : sigactionrec = (sa_handler:{$ifndef ver1_9_6}{$ifndef ver1_9_4}{$ifndef ver1_0}SigActionHandler{$endif}{$endif}{$endif}(lsignal_handler));
  156. {$endif}
  157. {$endif}
  158. {$endif}
  159. {$endif}
  160. {$endif}
  161. procedure starthandlesignal(signal:integer);
  162. begin
  163. if signal in ([0..31]-[sigkill,sigstop]) then begin
  164. sigprocmask(SIG_BLOCK,@blockset,nil);
  165. sigaction(signal,@saction,nil)
  166. end else begin
  167. raise exception.create('invalid signal number')
  168. end;
  169. end;
  170. initialization
  171. fillchar(blockset,sizeof(blockset),0);
  172. blockset[0] := $FFFFFFFF - (1 shl sigstop) - (1 shl sigkill) - (1 shl sigsegv);
  173. {$ifdef ver1_0}
  174. saction.sa_mask := blockset[0];
  175. {$else}
  176. saction.sa_mask := blockset;
  177. {$endif}
  178. end.