fpcatch.pas 5.8 KB

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