MessageBox "Abnormal program termination" supports my application

... view. As illustrated by this extremely simplified example,

enter image description here

very rarely (only once reported so far), it happens that one of my applications crashes this way. I want to end it as usual when a nonspecific exception occurs. My strategy is to (low level) log the problem and then complete. The application is part of a subsystem, and I want to (re) run it if any problem is detected. It is built with C ++ - Builder 6 and works on Windows (XP ... 7, also 8). I found out that abort() most likely caused an error message. The application has a graphical interface, so a message box is shown instead of just displaying (unlocking) on stderr .

And while the message box is not accepted by the user, my application works explicitly , for example, it processes timers (life bits in the increase example above) or interprocess communication messages, completely unaware of the problem.

After reading some answers to What is the easiest way to make a C ++ program crash? and the difference between raising (SIGABRT) and abort () , I tried the following

 void mySignalHandler(int sig) { // low-level error reporting here exit(-1); } void __fastcall TForm1::FormCreate(TObject *Sender) { signal(SIGABRT, mySignalHandler); // some more initialisation here } 

which allows my application to finish correctly also if abort() or raise(SIGABRT) called. (I also want Windows not to "look for a solution to the problem.")

Is this (registering a signal handler for interruption and call output there) reliable from your point of view? ... or at least something that you can rely on?

+6
source share
4 answers

In the C ++ Builder installation folder, check the following files:

  • source \ cpprtl \ Source \ misc \ errormsg.c - implementation of _ErrorMessage
  • source \ cpprtl \ Source \ procses \ abort.c - an abort implementation that calls _ErrorMessage
  • source \ cpprtl \ Source \ misc \ assert.c is an _assert implementation that calls _ErrorMessage

errormsg.c defines an undocumented function pointer _messagefunc , which you can set to override the default behavior. Although it is undocumented and not declared in any header files, you can declare it as extern and access it this way. Using an example:

 extern int (_RTLENTRY * _EXPDATA _messagefunc)(char *msg); static int LogAndDie(char *msg) { LogMessageToSomeFile(msg); exit(1); return 0; } void InitializeErrorHandling() { _messagefunc = LogAndDie; } 
+4
source

You may be able to use the Windows error report to dump the process when an unhandled exception causes it to terminate. You can then view the dump in your free time and allow multiple parent processes or other watchdogs to restart your process. If you chose this strategy, you would not try to deal with the error in your code, but resolve it.

+1
source

If you want to capture any program output, you should look atexit () . If you want to capture all completion events, look at std :: set_terminate () ; if you want to throw all unexpected exceptions, look at std :: set_unexpected () . If you want to capture only abort() , you can call signal () using the signal value SIGABRT . You can also wrap your code with try{your code}catch(...){custom event handler} .

+1
source

I could do some tests, and I can only confirm that registering the SIGABRT signal handler is just NOOP.

I tried this with a very simple graphical interface written using VS2008 Express.

  • no framework, not .NET, but only Win API
  • one menu with Exit and Fatal
  • menu driven directly in WndProc
  • Fatal execute 1/0

Here is the result:

  • no special action => windows open a MessageBox indicating a fatal error ...
  • signal handler for SIGABRT => same MessageBox
  • C ++ try catch (...) => same MessageBox
  • SEH in WndProc: may catch the error!
  • SEH around the message loop: may catch the error!

If I put SEH bot handlers, then most internal (WndProc) catches.

It’s good for you that if this is enough to protect the message outline, and you don’t have to enter every WndProc.

The bad newbie is that I don't know the C ++ constructor and cannot tell where to find the message loop.

To give you the key, here is how I can protect the message loop in a WinAPI application:

 __try { while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } __except (EXCEPTION_EXECUTE_HANDLER){ ::MessageBox(NULL, _T("FATAL"), _T("MAIN"), MB_OK | MB_ICONERROR); } 

This way I can see my own message box, but nothing else, and if I comment on my message box, the application will quit quietly.

But ... since the message you are showing is not original Windows, I suspect that the C ++ creator already has such an exception handler in its message loop.

Hope this helps ...

+1
source

Source: https://habr.com/ru/post/1200309/


All Articles