fpcatch.pas 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. {$ifndef GABOR}
  46. var
  47. StopJmp : Jmp_Buf;
  48. const
  49. StopJmpValid : boolean = false;
  50. {$endif}
  51. Implementation
  52. uses
  53. {$ifdef FPC}
  54. keyboard,
  55. drivers,
  56. {$endif FPC}
  57. {$ifdef FVISION}
  58. FVConsts,
  59. {$else}
  60. Commands,
  61. {$endif}
  62. dos,app,msgbox,
  63. FPString,FPCompil,FPIDE;
  64. Const
  65. LastCtrlC : longint = 0;
  66. {$ifdef DEBUG}
  67. procedure Generate_SIGSEGV;
  68. var
  69. l : plongint;
  70. begin
  71. { Force a SIGSEGV }
  72. l:=$ffffffff;
  73. l^:=1;
  74. end;
  75. procedure Generate_SIGFPE;
  76. var
  77. x,y : real;
  78. begin
  79. { Force a SIGFPE }
  80. y:=-5;
  81. x:=sqrt(y);
  82. end;
  83. {$endif DEBUG}
  84. {$ifdef HasSignal}
  85. {$ifdef Unix}
  86. Procedure Catchsignal(Sig : Longint);cdecl;
  87. {$else}
  88. Function Catchsignal(Sig : longint):longint;
  89. {$endif}
  90. var MustQuit: boolean;
  91. begin
  92. case Sig of
  93. SIGSEGV : begin
  94. if StopJmpValid then
  95. LongJmp(StopJmp,SIGSEGV);
  96. if Assigned(Application) then IDEApp.Done;
  97. Writeln('Internal SIGSEGV Error caught');
  98. {$ifndef DEBUG}
  99. Halt;
  100. {$else DEBUG}
  101. RunError(216);
  102. {$endif DEBUG}
  103. end;
  104. SIGFPE : begin
  105. if StopJmpValid then
  106. LongJmp(StopJmp,SIGFPE);
  107. if Assigned(Application) then IDEApp.Done;
  108. Writeln('Internal SIGFPE Error caught');
  109. {$ifndef DEBUG}
  110. Halt;
  111. {$else DEBUG}
  112. RunError(207);
  113. {$endif DEBUG}
  114. end;
  115. SIGILL : begin
  116. if StopJmpValid then
  117. LongJmp(StopJmp,SIGILL);
  118. if Assigned(Application) then IDEApp.Done;
  119. Writeln('Internal SIGILL Error caught');
  120. {$ifndef DEBUG}
  121. Halt;
  122. {$else DEBUG}
  123. RunError(216);
  124. {$endif DEBUG}
  125. end;
  126. SIGINT : begin
  127. if StopJmpValid then
  128. LongJmp(StopJmp,SIGINT);
  129. IF NOT CtrlCPressed and Assigned(Application) then
  130. begin
  131. MustQuit:=false;
  132. {$ifdef FPC}
  133. if GetDosTicks>LastCtrlC+10 then
  134. begin
  135. CtrlCPressed:=true;
  136. Keyboard.PutKeyEvent((kbCtrl shl 16) or kbCtrlC);
  137. LastCtrlC:=GetDosTicks;
  138. end;
  139. {$endif FPC}
  140. end
  141. else
  142. begin
  143. if Assigned(Application) then
  144. MustQuit:=MessageBox(#3+msg_QuitConfirm,nil,mferror+mfyesbutton+mfnobutton)=cmYes
  145. else
  146. MustQuit:=true;
  147. end;
  148. if MustQuit then
  149. begin
  150. if Assigned(Application) then IDEApp.Done;
  151. {$ifndef DEBUG}
  152. Halt;
  153. {$else DEBUG}
  154. RunError(216);
  155. {$endif DEBUG}
  156. end;
  157. end;
  158. end;
  159. {$ifndef Unix}
  160. CatchSignal:=0;
  161. {$endif}
  162. end;
  163. {$endif def HasSignal}
  164. Const
  165. CatchSignalsEnabled : boolean = false;
  166. Procedure EnableCatchSignals;
  167. {$ifdef win32}
  168. var Mode: DWORD;
  169. {$endif win32}
  170. begin
  171. if CatchSignalsEnabled then
  172. exit;
  173. {$ifdef win32}
  174. if GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @Mode) then
  175. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), (Mode or ENABLE_MOUSE_INPUT) and not ENABLE_PROCESSED_INPUT);
  176. {$endif win32}
  177. {$ifdef go32v2}
  178. djgpp_set_ctrl_c(false);
  179. {$endif go32v2}
  180. {$ifdef HasSignal}
  181. {$ifndef TP}
  182. NewSignal:=SignalHandler(@CatchSignal);
  183. {$else TP}
  184. NewSignal:=SignalHandler(CatchSignal);
  185. {$endif TP}
  186. OldSigSegm:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,NewSignal);
  187. OldSigInt:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,NewSignal);
  188. OldSigFPE:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,NewSignal);
  189. OldSigILL:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,NewSignal);
  190. CatchSignalsEnabled:=true;
  191. {$endif}
  192. end;
  193. Procedure DisableCatchSignals;
  194. begin
  195. {$ifdef HasSignal}
  196. if not CatchSignalsEnabled then
  197. exit;
  198. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,OldSigSegm);
  199. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,OldSigInt);
  200. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,OldSigFPE);
  201. {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,OldSigILL);
  202. CatchSignalsEnabled:=false;
  203. {$endif}
  204. end;
  205. end.
  206. {
  207. $Log$
  208. Revision 1.9 2003-09-29 14:36:59 peter
  209. * win32 fixed
  210. Revision 1.8 2003/09/27 14:03:45 peter
  211. * fixed for unix
  212. Revision 1.7 2003/04/23 09:49:26 peter
  213. * unix signal handler needs longint
  214. Revision 1.6 2002/09/07 21:04:41 carl
  215. * fix range check errors for version 1.1 compilation
  216. Revision 1.5 2002/09/07 15:40:42 peter
  217. * old logs removed and tabs fixed
  218. Revision 1.4 2002/03/20 14:48:27 pierre
  219. * moved StopJmp buffer to fpcatch unit
  220. }