fpcatch.pas 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 by Michael Van Canneyt
  4. Unit to catch segmentation faults and Ctrl-C and exit gracefully
  5. under linux and go32v2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Unit fpcatch;
  13. interface
  14. {$i globdir.inc}
  15. {$ifdef Unix}
  16. uses
  17. {$ifdef VER1_0}
  18. linux;
  19. {$else}
  20. baseunix,
  21. unix;
  22. {$endif}
  23. {$endif}
  24. {$ifdef go32v2}
  25. uses
  26. dpmiexcp;
  27. {$endif}
  28. {$ifdef win32}
  29. uses
  30. windows, signals;
  31. {$endif}
  32. {$ifdef HasSignal}
  33. Var
  34. NewSignal,OldSigSegm,OldSigILL,
  35. OldSigInt,OldSigFPE : SignalHandler;
  36. {$endif}
  37. Const
  38. CtrlCPressed : Boolean = false;
  39. Procedure EnableCatchSignals;
  40. Procedure DisableCatchSignals;
  41. {$ifdef DEBUG}
  42. procedure Generate_SIGSEGV;
  43. procedure Generate_SIGFPE;
  44. {$endif DEBUG}
  45. var
  46. StopJmp : Jmp_Buf;
  47. const
  48. StopJmpValid : boolean = false;
  49. Implementation
  50. uses
  51. keyboard,
  52. drivers,
  53. FVConsts,
  54. dos,app,msgbox,
  55. FPString,FPCompil,FPIDE;
  56. Const
  57. LastCtrlC : longint = 0;
  58. {$ifdef DEBUG}
  59. procedure Generate_SIGSEGV;
  60. var
  61. l : plongint;
  62. begin
  63. { Force a SIGSEGV }
  64. l:=pointer (ptrint ($ffffffff));
  65. l^:=1;
  66. end;
  67. procedure Generate_SIGFPE;
  68. var
  69. x,y : real;
  70. begin
  71. { Force a SIGFPE }
  72. y:=-5;
  73. x:=sqrt(y);
  74. end;
  75. {$endif DEBUG}
  76. {$ifdef HasSignal}
  77. {$ifdef Unix}
  78. Procedure Catchsignal(Sig : Longint);cdecl;
  79. {$else}
  80. Function Catchsignal(Sig : longint):longint;
  81. {$endif}
  82. var MustQuit: boolean;
  83. begin
  84. case Sig of
  85. SIGSEGV : begin
  86. if StopJmpValid then
  87. LongJmp(StopJmp,SIGSEGV);
  88. if Assigned(Application) then IDEApp.Done;
  89. Writeln('Internal SIGSEGV Error caught');
  90. {$ifndef DEBUG}
  91. Halt;
  92. {$else DEBUG}
  93. RunError(216);
  94. {$endif DEBUG}
  95. end;
  96. SIGFPE : begin
  97. if StopJmpValid then
  98. LongJmp(StopJmp,SIGFPE);
  99. if Assigned(Application) then IDEApp.Done;
  100. Writeln('Internal SIGFPE Error caught');
  101. {$ifndef DEBUG}
  102. Halt;
  103. {$else DEBUG}
  104. RunError(207);
  105. {$endif DEBUG}
  106. end;
  107. SIGILL : begin
  108. if StopJmpValid then
  109. LongJmp(StopJmp,SIGILL);
  110. if Assigned(Application) then IDEApp.Done;
  111. Writeln('Internal SIGILL Error caught');
  112. {$ifndef DEBUG}
  113. Halt;
  114. {$else DEBUG}
  115. RunError(216);
  116. {$endif DEBUG}
  117. end;
  118. SIGINT : begin
  119. if StopJmpValid then
  120. LongJmp(StopJmp,SIGINT);
  121. IF NOT CtrlCPressed and Assigned(Application) then
  122. begin
  123. MustQuit:=false;
  124. {$ifdef FPC}
  125. if GetDosTicks>LastCtrlC+10 then
  126. begin
  127. CtrlCPressed:=true;
  128. Keyboard.PutKeyEvent((kbCtrl shl 16) or kbCtrlC);
  129. LastCtrlC:=GetDosTicks;
  130. end;
  131. {$endif FPC}
  132. end
  133. else
  134. begin
  135. if Assigned(Application) then
  136. MustQuit:=MessageBox(#3+msg_QuitConfirm,nil,mferror+mfyesbutton+mfnobutton)=cmYes
  137. else
  138. MustQuit:=true;
  139. end;
  140. if MustQuit then
  141. begin
  142. if Assigned(Application) then IDEApp.Done;
  143. {$ifndef DEBUG}
  144. Halt;
  145. {$else DEBUG}
  146. RunError(216);
  147. {$endif DEBUG}
  148. end;
  149. end;
  150. end;
  151. {$ifndef Unix}
  152. CatchSignal:=0;
  153. {$endif}
  154. end;
  155. {$endif def HasSignal}
  156. Const
  157. CatchSignalsEnabled : boolean = false;
  158. Procedure EnableCatchSignals;
  159. {$ifdef win32}
  160. var Mode: DWORD;
  161. {$endif win32}
  162. begin
  163. if CatchSignalsEnabled then
  164. exit;
  165. {$ifdef win32}
  166. if GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @Mode) then
  167. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), (Mode or ENABLE_MOUSE_INPUT) and not ENABLE_PROCESSED_INPUT);
  168. {$endif win32}
  169. {$ifdef go32v2}
  170. djgpp_set_ctrl_c(false);
  171. {$endif go32v2}
  172. {$ifdef HasSignal}
  173. {$ifndef TP}
  174. NewSignal:=SignalHandler(@CatchSignal);
  175. {$else TP}
  176. NewSignal:=SignalHandler(CatchSignal);
  177. {$endif TP}
  178. OldSigSegm:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,NewSignal);
  179. OldSigInt:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,NewSignal);
  180. OldSigFPE:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,NewSignal);
  181. OldSigILL:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,NewSignal);
  182. CatchSignalsEnabled:=true;
  183. {$endif}
  184. end;
  185. Procedure DisableCatchSignals;
  186. begin
  187. {$ifdef HasSignal}
  188. if not CatchSignalsEnabled then
  189. exit;
  190. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,OldSigSegm);
  191. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,OldSigInt);
  192. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,OldSigFPE);
  193. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,OldSigILL);
  194. CatchSignalsEnabled:=false;
  195. {$endif}
  196. end;
  197. end.
  198. {
  199. $Log$
  200. Revision 1.11 2004-11-08 20:28:26 peter
  201. * Breakpoints are now deleted when removed from source, disabling is
  202. still possible from the breakpoint list
  203. * COMPILER_1_0, FVISION, GABOR defines removed, only support new
  204. FV and 1.9.x compilers
  205. * Run directory added to Run menu
  206. * Useless programinfo window removed
  207. Revision 1.10 2004/09/15 19:23:26 hajny
  208. * corrections for debug mode
  209. Revision 1.9 2003/09/29 14:36:59 peter
  210. * win32 fixed
  211. Revision 1.8 2003/09/27 14:03:45 peter
  212. * fixed for unix
  213. Revision 1.7 2003/04/23 09:49:26 peter
  214. * unix signal handler needs longint
  215. Revision 1.6 2002/09/07 21:04:41 carl
  216. * fix range check errors for version 1.1 compilation
  217. Revision 1.5 2002/09/07 15:40:42 peter
  218. * old logs removed and tabs fixed
  219. Revision 1.4 2002/03/20 14:48:27 pierre
  220. * moved StopJmp buffer to fpcatch unit
  221. }