Skip to content

Commit c120149

Browse files
authored
Exit tests shouldn't emit crash logs. (#670)
When a process crashes, the platforms we support all write a crash log (or core, or error report) to disk. This is not necessary for exit test child processes (since we intentionally crash them.) This PR suppresses generation of those logs from within an exit test: - On Darwin, we disable the exception port for crash report files; - On Linux, we set the maximum core dump size to zero bytes; and - On Windows, we disable Windows Error Reporting. The above effects are only applied to the exit test's child process, not to the parent test process nor the system as a whole. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent 2e9df4f commit c120149

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

Sources/Testing/ExitTests/ExitTest.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,39 @@ public struct ExitTest: Sendable {
2929
/// processes, so it can be used to uniquely identify an exit test at runtime.
3030
public var sourceLocation: SourceLocation
3131

32+
/// Disable crash reporting, crash logging, or core dumps for the current
33+
/// process.
34+
private static func _disableCrashReporting() {
35+
#if SWT_TARGET_OS_APPLE && !SWT_NO_MACH_PORTS
36+
// We don't need to create a crash log (a "corpse notification") for an exit
37+
// test. In the future, we might want to investigate actually setting up a
38+
// listener port in the parent process and tracking interesting exceptions
39+
// as separate exit conditions.
40+
//
41+
// BUG: The system may still opt to write crash logs to /Library/Logs
42+
// instead of the user's home folder. rdar://47982238
43+
_ = task_set_exception_ports(
44+
swt_mach_task_self(),
45+
exception_mask_t(EXC_MASK_CORPSE_NOTIFY),
46+
mach_port_t(MACH_PORT_NULL),
47+
EXCEPTION_DEFAULT,
48+
THREAD_STATE_NONE
49+
)
50+
#elseif os(Linux)
51+
// On Linux, disable the generation of core files (although they will often
52+
// be disabled by default.) If a particular Linux distro performs additional
53+
// crash diagnostics, we may want to special-case them as well if we can.
54+
var rl = rlimit(rlim_cur: 0, rlim_max: 0)
55+
_ = setrlimit(CInt(RLIMIT_CORE.rawValue), &rl)
56+
#elseif os(Windows)
57+
// On Windows, similarly disable Windows Error Reporting and the Windows
58+
// Error Reporting UI. Note we expect to be the first component to call
59+
// these functions, so we don't attempt to preserve any previously-set bits.
60+
_ = SetErrorMode(UINT(SEM_NOGPFAULTERRORBOX))
61+
_ = WerSetFlags(DWORD(WER_FAULT_REPORTING_NO_UI))
62+
#endif
63+
}
64+
3265
/// Call the exit test in the current process.
3366
///
3467
/// This function invokes the closure originally passed to
@@ -37,6 +70,8 @@ public struct ExitTest: Sendable {
3770
/// terminate the process in a way that causes the corresponding expectation
3871
/// to fail.
3972
public func callAsFunction() async -> Never {
73+
Self._disableCrashReporting()
74+
4075
do {
4176
try await body()
4277
} catch {

Sources/_TestingInternals/include/Includes.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@
3939
#include <string.h>
4040
#include <time.h>
4141

42-
#if defined(__APPLE__) && __has_include(<dispatch/dispatch.h>)
42+
#if defined(__APPLE__) && !SWT_NO_MACH_PORTS
43+
#include <mach/mach_init.h>
44+
#include <mach/task.h>
45+
#endif
46+
47+
#if defined(__APPLE__) && !SWT_NO_LIBDISPATCH
4348
#include <dispatch/dispatch.h>
4449
#endif
4550

@@ -53,6 +58,10 @@
5358
#include <sys/fcntl.h>
5459
#endif
5560

61+
#if __has_include(<sys/resource.h>)
62+
#include <sys/resource.h>
63+
#endif
64+
5665
#if __has_include(<sys/stat.h>)
5766
#include <sys/stat.h>
5867
#endif

Sources/_TestingInternals/include/Stubs.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ static bool swt_S_ISFIFO(mode_t mode) {
6464
#endif
6565
#endif
6666

67+
#if defined(__APPLE__) && !SWT_NO_MACH_PORTS
68+
/// Get a Mach port representing the current task (process.)
69+
///
70+
/// This function is provided because `mach_task_self()` is a complex macro, but
71+
/// directly accessing `mach_task_self_` from Swift triggers concurrency
72+
/// warnings about accessing shared mutable state.
73+
static mach_port_t swt_mach_task_self(void) {
74+
return mach_task_self();
75+
}
76+
#endif
77+
6778
#if defined(_WIN32)
6879
/// Make a Win32 language ID.
6980
///

0 commit comments

Comments
 (0)