123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- {
- Copyright (c) 1997-98 by Michael Van Canneyt
- Unit to catch segmentation faults and Ctrl-C and exit gracefully
- under linux and go32v2
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- Unit fpcatch;
- interface
- {$i globdir.inc}
- {$ifdef Unix}
- uses
- {$ifdef VER1_0}
- linux;
- {$else}
- baseunix,
- unix;
- {$endif}
- {$endif}
- {$ifdef go32v2}
- uses
- dpmiexcp;
- {$endif}
- {$ifdef Windows}
- uses
- windows
- {$ifdef HasSignal}
- ,signals
- {$endif}
- ;
- {$endif}
- {$ifdef HasSignal}
- Var
- NewSignal,OldSigSegm,OldSigILL,
- OldSigInt,OldSigFPE : SignalHandler;
- {$endif}
- Const
- CtrlCPressed : Boolean = false;
- Procedure EnableCatchSignals;
- Procedure DisableCatchSignals;
- {$ifdef DEBUG}
- procedure Generate_SIGSEGV;
- procedure Generate_SIGFPE;
- {$endif DEBUG}
- var
- StopJmp : Jmp_Buf;
- const
- StopJmpValid : boolean = false;
- {$IFNDEF HASSIGNAL}
- const
- SIGABRT = 288;
- SIGFPE = 289;
- SIGILL = 290;
- SIGSEGV = 291;
- SIGTERM = 292;
- SIGALRM = 293;
- SIGHUP = 294;
- SIGINT = 295;
- SIGKILL = 296;
- SIGPIPE = 297;
- SIGQUIT = 298;
- SIGUSR1 = 299;
- SIGUSR2 = 300;
- SIGNOFP = 301;
- SIGTRAP = 302;
- SIGTIMR = 303; { Internal for setitimer (SIGALRM, SIGPROF) }
- SIGPROF = 304;
- SIGMAX = 320;
- SIG_BLOCK = 1;
- SIG_SETMASK = 2;
- SIG_UNBLOCK = 3;
- {$ENDIF HASSIGNAL}
- Implementation
- uses
- keyboard,
- drivers,
- FVConsts,
- dos,app,msgbox,
- FPCompil,FPIDE;
- Const
- LastCtrlC : longint = 0;
- {$ifdef useresstrings}
- resourcestring
- {$else}
- const
- {$endif}
- msg_quitconfirm = 'Do You really want to quit?';
- {$ifdef DEBUG}
- procedure Generate_SIGSEGV;
- var
- l : plongint;
- begin
- { Force a SIGSEGV }
- l:=pointer (ptrint ($ffffffff));
- l^:=1;
- end;
- procedure Generate_SIGFPE;
- var
- x,y : real;
- begin
- { Force a SIGFPE }
- y:=-5;
- x:=sqrt(y);
- end;
- {$endif DEBUG}
- {$ifdef HasSignal}
- {$ifndef SignalIsFunction}
- Procedure Catchsignal(Sig : Longint);cdecl;
- {$else SignalIsFunction}
- {$ifdef SignalIsCdecl}
- Function Catchsignal(Sig : longint):longint; cdecl;
- {$else not SignalIsCdecl}
- Function Catchsignal(Sig : longint):longint;
- {$endif not SignalIsCdecl}
- {$endif SignalIsFunction}
- var MustQuit: boolean;
- begin
- case Sig of
- SIGSEGV : begin
- if StopJmpValid then
- LongJmp(StopJmp,SIGSEGV);
- if Assigned(Application) then IDEApp.Done;
- Writeln('Internal SIGSEGV Error caught');
- {$ifndef DEBUG}
- Halt;
- {$else DEBUG}
- RunError(216);
- {$endif DEBUG}
- end;
- SIGFPE : begin
- if StopJmpValid then
- LongJmp(StopJmp,SIGFPE);
- if Assigned(Application) then IDEApp.Done;
- Writeln('Internal SIGFPE Error caught');
- {$ifndef DEBUG}
- Halt;
- {$else DEBUG}
- RunError(207);
- {$endif DEBUG}
- end;
- SIGILL : begin
- if StopJmpValid then
- LongJmp(StopJmp,SIGILL);
- if Assigned(Application) then IDEApp.Done;
- Writeln('Internal SIGILL Error caught');
- {$ifndef DEBUG}
- Halt;
- {$else DEBUG}
- RunError(216);
- {$endif DEBUG}
- end;
- SIGINT : begin
- if StopJmpValid then
- LongJmp(StopJmp,SIGINT);
- IF NOT CtrlCPressed and Assigned(Application) then
- begin
- MustQuit:=false;
- {$ifdef FPC}
- if GetDosTicks>LastCtrlC+10 then
- begin
- CtrlCPressed:=true;
- Keyboard.PutKeyEvent((kbCtrl shl 16) or kbCtrlC);
- LastCtrlC:=GetDosTicks;
- end;
- {$endif FPC}
- end
- else
- begin
- if Assigned(Application) then
- MustQuit:=MessageBox(#3+msg_QuitConfirm,nil,mferror+mfyesbutton+mfnobutton)=cmYes
- else
- MustQuit:=true;
- end;
- if MustQuit then
- begin
- if Assigned(Application) then IDEApp.Done;
- {$ifndef DEBUG}
- Halt;
- {$else DEBUG}
- RunError(216);
- {$endif DEBUG}
- end;
- end;
- end;
- {$ifdef SignalIsFunction}
- CatchSignal:=0;
- {$endif SignalIsFunction}
- end;
- {$endif def HasSignal}
- Const
- CatchSignalsEnabled : boolean = false;
- Procedure EnableCatchSignals;
- {$ifdef Windows}
- var Mode: DWORD;
- {$endif Windows}
- begin
- if CatchSignalsEnabled then
- exit;
- {$ifdef Windows}
- if GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @Mode) then
- begin
- {$ifdef DEBUG}
- Writeln(stderr,'Starting value of ConsoleMode is $',hexstr(Mode,8));
- {$endif DEBUG}
- SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)),
- (Mode or ENABLE_MOUSE_INPUT) and not ENABLE_PROCESSED_INPUT);
- {$ifdef DEBUG}
- end
- else
- begin
- Writeln(stderr,'Call to GetConsoleMode failed, GetLastError=',
- GetLastError);
- {$endif DEBUG}
- end;
- {$endif Windows}
- {$ifdef go32v2}
- {
- I think that it was an error to put that here PM
- djgpp_set_ctrl_c(false);
- at least since that this is now handled in fpusrscr.pas unit
- }
- {$endif go32v2}
- {$ifdef HasSignal}
- {$ifndef TP}
- NewSignal:=@CatchSignal;
- {$else TP}
- NewSignal:=SignalHandler(CatchSignal);
- {$endif TP}
- OldSigSegm:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,NewSignal);
- OldSigInt:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,NewSignal);
- OldSigFPE:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,NewSignal);
- OldSigILL:={$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,NewSignal);
- CatchSignalsEnabled:=true;
- {$endif}
- end;
- Procedure DisableCatchSignals;
- begin
- {$ifdef HasSignal}
- if not CatchSignalsEnabled then
- exit;
- {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGSEGV,OldSigSegm);
- {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGINT,OldSigInt);
- {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGFPE,OldSigFPE);
- {$ifdef unix}{$ifdef ver1_0}Signal{$else}fpSignal{$endif}{$else}Signal{$endif}(SIGILL,OldSigILL);
- CatchSignalsEnabled:=false;
- {$endif}
- end;
- end.
|