fpcatch.pas 6.0 KB

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