fpcatch.pas 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. {
  2. Copyright (c) 1997-98 by Michael Van Canneyt
  3. Unit to catch segmentation faults and Ctrl-C and exit gracefully
  4. under linux and go32v2
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. Unit fpcatch;
  12. interface
  13. {$i globdir.inc}
  14. {$ifdef Unix}
  15. uses
  16. {$ifdef VER1_0}
  17. linux;
  18. {$else}
  19. baseunix,
  20. unix;
  21. {$endif}
  22. {$endif}
  23. {$ifdef go32v2}
  24. uses
  25. dpmiexcp;
  26. {$endif}
  27. {$ifdef Windows}
  28. uses
  29. windows
  30. {$ifdef HasSignal}
  31. ,signals
  32. {$endif}
  33. ;
  34. {$endif}
  35. {$ifdef HasSignal}
  36. Var
  37. NewSignal,OldSigSegm,OldSigILL,
  38. OldSigInt,OldSigFPE : SignalHandler;
  39. {$endif}
  40. Const
  41. CtrlCPressed : Boolean = false;
  42. Procedure EnableCatchSignals;
  43. Procedure DisableCatchSignals;
  44. {$ifdef DEBUG}
  45. procedure Generate_SIGSEGV;
  46. procedure Generate_SIGFPE;
  47. {$endif DEBUG}
  48. var
  49. StopJmp : Jmp_Buf;
  50. const
  51. StopJmpValid : boolean = false;
  52. {$IFNDEF HASSIGNAL}
  53. const
  54. SIGABRT = 288;
  55. SIGFPE = 289;
  56. SIGILL = 290;
  57. SIGSEGV = 291;
  58. SIGTERM = 292;
  59. SIGALRM = 293;
  60. SIGHUP = 294;
  61. SIGINT = 295;
  62. SIGKILL = 296;
  63. SIGPIPE = 297;
  64. SIGQUIT = 298;
  65. SIGUSR1 = 299;
  66. SIGUSR2 = 300;
  67. SIGNOFP = 301;
  68. SIGTRAP = 302;
  69. SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
  70. SIGPROF = 304;
  71. SIGMAX = 320;
  72. SIG_BLOCK = 1;
  73. SIG_SETMASK = 2;
  74. SIG_UNBLOCK = 3;
  75. {$ENDIF HASSIGNAL}
  76. Implementation
  77. uses
  78. keyboard,
  79. drivers,
  80. FVConsts,
  81. dos,app,msgbox,
  82. FPString,FPCompil,FPIDE;
  83. Const
  84. LastCtrlC : longint = 0;
  85. {$ifdef DEBUG}
  86. procedure Generate_SIGSEGV;
  87. var
  88. l : plongint;
  89. begin
  90. { Force a SIGSEGV }
  91. l:=pointer (ptrint ($ffffffff));
  92. l^:=1;
  93. end;
  94. procedure Generate_SIGFPE;
  95. var
  96. x,y : real;
  97. begin
  98. { Force a SIGFPE }
  99. y:=-5;
  100. x:=sqrt(y);
  101. end;
  102. {$endif DEBUG}
  103. {$ifdef HasSignal}
  104. {$ifdef Unix}
  105. Procedure Catchsignal(Sig : Longint);cdecl;
  106. {$else}
  107. Function Catchsignal(Sig : longint):longint;
  108. {$endif}
  109. var MustQuit: boolean;
  110. begin
  111. case Sig of
  112. SIGSEGV : begin
  113. if StopJmpValid then
  114. LongJmp(StopJmp,SIGSEGV);
  115. if Assigned(Application) then IDEApp.Done;
  116. Writeln('Internal SIGSEGV Error caught');
  117. {$ifndef DEBUG}
  118. Halt;
  119. {$else DEBUG}
  120. RunError(216);
  121. {$endif DEBUG}
  122. end;
  123. SIGFPE : begin
  124. if StopJmpValid then
  125. LongJmp(StopJmp,SIGFPE);
  126. if Assigned(Application) then IDEApp.Done;
  127. Writeln('Internal SIGFPE Error caught');
  128. {$ifndef DEBUG}
  129. Halt;
  130. {$else DEBUG}
  131. RunError(207);
  132. {$endif DEBUG}
  133. end;
  134. SIGILL : begin
  135. if StopJmpValid then
  136. LongJmp(StopJmp,SIGILL);
  137. if Assigned(Application) then IDEApp.Done;
  138. Writeln('Internal SIGILL Error caught');
  139. {$ifndef DEBUG}
  140. Halt;
  141. {$else DEBUG}
  142. RunError(216);
  143. {$endif DEBUG}
  144. end;
  145. SIGINT : begin
  146. if StopJmpValid then
  147. LongJmp(StopJmp,SIGINT);
  148. IF NOT CtrlCPressed and Assigned(Application) then
  149. begin
  150. MustQuit:=false;
  151. {$ifdef FPC}
  152. if GetDosTicks>LastCtrlC+10 then
  153. begin
  154. CtrlCPressed:=true;
  155. Keyboard.PutKeyEvent((kbCtrl shl 16) or kbCtrlC);
  156. LastCtrlC:=GetDosTicks;
  157. end;
  158. {$endif FPC}
  159. end
  160. else
  161. begin
  162. if Assigned(Application) then
  163. MustQuit:=MessageBox(#3+msg_QuitConfirm,nil,mferror+mfyesbutton+mfnobutton)=cmYes
  164. else
  165. MustQuit:=true;
  166. end;
  167. if MustQuit then
  168. begin
  169. if Assigned(Application) then IDEApp.Done;
  170. {$ifndef DEBUG}
  171. Halt;
  172. {$else DEBUG}
  173. RunError(216);
  174. {$endif DEBUG}
  175. end;
  176. end;
  177. end;
  178. {$ifndef Unix}
  179. CatchSignal:=0;
  180. {$endif}
  181. end;
  182. {$endif def HasSignal}
  183. Const
  184. CatchSignalsEnabled : boolean = false;
  185. Procedure EnableCatchSignals;
  186. {$ifdef Windows}
  187. var Mode: DWORD;
  188. {$endif Windows}
  189. begin
  190. if CatchSignalsEnabled then
  191. exit;
  192. {$ifdef Windows}
  193. if GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @Mode) then
  194. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), (Mode or ENABLE_MOUSE_INPUT) and not ENABLE_PROCESSED_INPUT);
  195. {$endif Windows}
  196. {$ifdef go32v2}
  197. djgpp_set_ctrl_c(false);
  198. {$endif go32v2}
  199. {$ifdef HasSignal}
  200. {$ifndef TP}
  201. NewSignal:=SignalHandler(@CatchSignal);
  202. {$else TP}
  203. NewSignal:=SignalHandler(CatchSignal);
  204. {$endif TP}
  205. OldSigSegm:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,NewSignal);
  206. OldSigInt:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,NewSignal);
  207. OldSigFPE:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,NewSignal);
  208. OldSigILL:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,NewSignal);
  209. CatchSignalsEnabled:=true;
  210. {$endif}
  211. end;
  212. Procedure DisableCatchSignals;
  213. begin
  214. {$ifdef HasSignal}
  215. if not CatchSignalsEnabled then
  216. exit;
  217. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,OldSigSegm);
  218. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,OldSigInt);
  219. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,OldSigFPE);
  220. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,OldSigILL);
  221. CatchSignalsEnabled:=false;
  222. {$endif}
  223. end;
  224. end.