diff -r 80db7232b4b5 -r 282218ab1b28 hedgewars/hwengine.pas --- a/hedgewars/hwengine.pas Sat Jul 21 02:19:32 2018 +0300 +++ b/hedgewars/hwengine.pas Fri Jul 20 20:00:52 2018 -0400 @@ -45,12 +45,14 @@ procedure preInitEverything(); procedure initEverything(complete:boolean); procedure freeEverything(complete:boolean); +procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer); implementation {$ELSE} procedure preInitEverything(); forward; procedure initEverything(complete:boolean); forward; procedure freeEverything(complete:boolean); forward; +procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer); forward; {$ENDIF} {$IFDEF WIN32} @@ -597,6 +599,28 @@ freeEverything(false); end; +// Write backtrace to console and log when an unhandled exception occurred +procedure catchUnhandledException(Obj: TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer); +var + Message: string; + i: LongInt; +begin + WriteLnToConsole('An unhandled exception occurred at $' + HexStr(Addr) + ':'); + if Obj is exception then + begin + Message := Exception(Obj).ClassName + ': ' + Exception(Obj).Message; + WriteLnToConsole(Message); + end + else + WriteLnToConsole('Exception object ' + Obj.ClassName + ' is not of class Exception.'); + WriteLnToConsole(BackTraceStrFunc(Addr)); + if (FrameCount > 0) then + begin + for i := 0 to FrameCount - 1 do + WriteLnToConsole(BackTraceStrFunc(Frames[i])); + end; +end; + {$IFDEF HWLIBRARY} function RunEngine(argc: LongInt; argv: PPChar): LongInt; cdecl; export; begin @@ -624,17 +648,20 @@ // workaround for pascal's ParamStr and ParamCount init(argc, argv); {$ENDIF} + // Custom procedure for unhandled exceptions; ExceptProc is used by sysutils module + ExceptProc:= @catchUnhandledException; + preInitEverything(); GetParams(); if GameType = gmtLandPreview then GenLandPreview() - else if GameType <> gmtSyntax then + else if (GameType <> gmtBadSyntax) and (GameType <> gmtSyntaxHelp) then Game(); - // return 1 when engine is not called correctly - if GameType = gmtSyntax then + // return error when engine is not called correctly + if GameType = gmtBadSyntax then {$IFDEF PAS2C} exit(HaltUsageError); {$ELSE}