Skip to content

Commit f3feff8

Browse files
committed
windows: Improve crash / assert / exception handling.
startup_hacks() called SetErrorMode() with the SEM_NOGPFAULTERRORBOX argument to prevent GUI popups on error. While that likely was sufficient at some point, there are other sources of error popups. At the same time SEM_NOGPFAULTERRORBOX unfortunately also prevents "just-in-time debuggers" from working reliably, i.e. the ability to attach to a process on crash. This prevents collecting crash dumps as part of CI. The error popups are particularly problematic when they occur during automated testing, as they can cause the tests to hang, waiting for a button to be clicked. This commit improves the error handling setup in startup_hacks() to address those problems. SEM_NOGPFAULTERRORBOX is not used anymore, instead various other APIs are used to disable popups and to redirect output to stderr where possible. While this improves the situation for postgres.exe, it doesn't address similar issues in all the other executables. There currently is no codepath that's called early on for all frontend programs. I've tested that this prevents GUI popups and allows JIT debugging in case of crashes due to: - abort() - assert() - C runtime errors - unhandled exceptions both in debug and non-debug mode, on Win10 with MSVC 2019 and with MinGW. Now that crash reports are generated on windows, collect them in windows CI. Discussion: https://postgr.es/m/[email protected]
1 parent 6dcc185 commit f3feff8

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

.cirrus.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,11 @@ task:
437437
cd src/tools/msvc
438438
%T_C% perl vcregress.pl ecpgcheck
439439
440-
on_failure: *on_failure
440+
on_failure:
441+
<<: *on_failure
442+
crashlog_artifacts:
443+
path: "crashlog-**.txt"
444+
type: text/plain
441445

442446

443447
task:

src/backend/main/main.c

+53-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
#include <unistd.h>
2424

25+
#if defined(WIN32)
26+
#include <crtdbg.h>
27+
#endif
28+
2529
#if defined(__NetBSD__)
2630
#include <sys/param.h>
2731
#endif
@@ -237,8 +241,55 @@ startup_hacks(const char *progname)
237241
exit(1);
238242
}
239243

240-
/* In case of general protection fault, don't show GUI popup box */
241-
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
244+
/*
245+
* By default abort() only generates a crash-dump in *non* debug
246+
* builds. As our Assert() / ExceptionalCondition() uses abort(),
247+
* leaving the default in place would make debugging harder.
248+
*
249+
* MINGW's own C runtime doesn't have _set_abort_behavior(). When
250+
* targetting Microsoft's UCRT with mingw, it never links to the debug
251+
* version of the library and thus doesn't need the call to
252+
* _set_abort_behavior() either.
253+
*/
254+
#if !defined(__MINGW32__) && !defined(__MINGW64__)
255+
_set_abort_behavior(_CALL_REPORTFAULT | _WRITE_ABORT_MSG,
256+
_CALL_REPORTFAULT | _WRITE_ABORT_MSG);
257+
#endif /* !defined(__MINGW32__) &&
258+
* !defined(__MINGW64__) */
259+
260+
/*
261+
* SEM_FAILCRITICALERRORS causes more errors to be reported to
262+
* callers.
263+
*
264+
* We used to also specify SEM_NOGPFAULTERRORBOX, but that prevents
265+
* windows crash reporting from working. Which includes registered
266+
* just-in-time debuggers, making it unnecessarily hard to debug
267+
* problems on windows. Now we try to disable sources of popups
268+
* separately below (note that SEM_NOGPFAULTERRORBOX did not actually
269+
* prevent all sources of such popups).
270+
*/
271+
SetErrorMode(SEM_FAILCRITICALERRORS);
272+
273+
/*
274+
* Show errors on stderr instead of popup box (note this doesn't
275+
* affect errors originating in the C runtime, see below).
276+
*/
277+
_set_error_mode(_OUT_TO_STDERR);
278+
279+
/*
280+
* In DEBUG builds, errors, including assertions, C runtime errors are
281+
* reported via _CrtDbgReport. By default such errors are displayed
282+
* with a popup (even with NOGPFAULTERRORBOX), preventing forward
283+
* progress. Instead report such errors stderr (and the debugger).
284+
* This is C runtime specific and thus the above incantations aren't
285+
* sufficient to suppress these popups.
286+
*/
287+
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
288+
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
289+
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
290+
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
291+
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
292+
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
242293

243294
#if defined(_M_AMD64) && _MSC_VER == 1800
244295

0 commit comments

Comments
 (0)