From 9b176032a967e52c45ce21782696f37a36bed214 Mon Sep 17 00:00:00 2001 From: Carl Peto Date: Tue, 28 Oct 2025 17:46:04 +0000 Subject: [PATCH 1/3] color=tty now correctly reflects whether stdout/stderr is a tty, as appropriate --- stdlib/public/runtime/Backtrace.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/stdlib/public/runtime/Backtrace.cpp b/stdlib/public/runtime/Backtrace.cpp index 18bad7bf620b6..595fbddb63330 100644 --- a/stdlib/public/runtime/Backtrace.cpp +++ b/stdlib/public/runtime/Backtrace.cpp @@ -221,6 +221,16 @@ char swiftBacktraceOutputPath[SWIFT_BACKTRACE_OUTPUT_PATH_SIZE] __attribute__((s void _swift_backtraceSetupEnvironment(); +bool isStderrATty() +{ +#ifndef _WIN32 + return isatty(STDERR_FILENO); +#else + DWORD dwMode; + return GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &dwMode); +#endif +} + bool isStdoutATty() { #ifndef _WIN32 @@ -412,10 +422,6 @@ BacktraceInitializer::BacktraceInitializer() { (isStdoutATty() && isStdinATty()) ? OnOffTty::On : OnOffTty::Off; } - if (_swift_backtraceSettings.color == OnOffTty::TTY) - _swift_backtraceSettings.color = - isStdoutATty() ? OnOffTty::On : OnOffTty::Off; - if (_swift_backtraceSettings.preset == Preset::Auto) { if (_swift_backtraceSettings.interactive == OnOffTty::On) _swift_backtraceSettings.preset = Preset::Friendly; @@ -454,6 +460,16 @@ BacktraceInitializer::BacktraceInitializer() { _swift_backtraceSettings.outputTo = OutputTo::Stderr; } + if (_swift_backtraceSettings.color == OnOffTty::TTY) { + bool outputToIsTty; + if (_swift_backtraceSettings.outputTo == OutputTo::Stderr) + outputToIsTty = isStderrATty(); + else + outputToIsTty = isStdoutATty(); + _swift_backtraceSettings.color = + outputToIsTty ? OnOffTty::On : OnOffTty::Off; + } + if (_swift_backtraceSettings.enabled == OnOffTty::On) { // Copy the path to swift-backtrace into swiftBacktracePath, then write // protect it so that it can't be overwritten easily at runtime. We do From fd6be28aa10c073b5cc676e9de44d5bf8095e205 Mon Sep 17 00:00:00 2001 From: Carl Peto Date: Fri, 14 Nov 2025 13:26:10 +0000 Subject: [PATCH 2/3] add unit tests for coloured/uncoloured output --- test/Backtracing/TTYDetection.swift | 73 +++++++++++++++++++ .../Backtracing/TTYDetectionColourLinux.swift | 46 ++++++++++++ .../Backtracing/TTYDetectionColourMacOS.swift | 46 ++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 test/Backtracing/TTYDetection.swift create mode 100644 test/Backtracing/TTYDetectionColourLinux.swift create mode 100644 test/Backtracing/TTYDetectionColourMacOS.swift diff --git a/test/Backtracing/TTYDetection.swift b/test/Backtracing/TTYDetection.swift new file mode 100644 index 0000000000000..51e8af15233b3 --- /dev/null +++ b/test/Backtracing/TTYDetection.swift @@ -0,0 +1,73 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection +// RUN: %target-codesign %t/TTYDetection + +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no %target-run %t/TTYDetection 2> %t/default-output || true) && cat %t/default-output | %FileCheck %s +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,output-to=stderr %target-run %t/TTYDetection 2> %t/stderr-output || true) && cat %t/stderr-output | %FileCheck %s --check-prefix STDERR +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,output-to=stdout %target-run %t/TTYDetection > %t/stdout-output || true) && cat %t/stdout-output | %FileCheck %s --check-prefix STDOUT + + +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime +// UNSUPPORTED: asan +// REQUIRES: executable_test +// REQUIRES: backtracing +// REQUIRES: OS=macosx || OS=linux-gnu +// COM: we should be able to add Windows to this test + +func level1() { + level2() +} + +func level2() { + level3() +} + +func level3() { + level4() +} + +func level4() { + level5() +} + +func level5() { + print("About to crash") + let ptr = UnsafeMutablePointer(bitPattern: 4)! + ptr.pointee = 42 +} + +@main +struct TTYDetection { + static func main() { + level1() + } +} + +// CHECK: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 *** + +// CHECK: Thread 0 {{(".*" )?}}crashed: + +// CHECK: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection +// CHECK-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection +// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection +// CHECK-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection + + +// STDERR: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 *** + +// STDERR: Thread 0 {{(".*" )?}}crashed: + +// STDERR: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection +// STDERR-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection +// STDERR-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection +// STDERR-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection + +// STDOUT: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 *** + +// STDOUT: Thread 0 {{(".*" )?}}crashed: + +// STDOUT: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection +// STDOUT-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection +// STDOUT-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection +// STDOUT-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection diff --git a/test/Backtracing/TTYDetectionColourLinux.swift b/test/Backtracing/TTYDetectionColourLinux.swift new file mode 100644 index 0000000000000..6cf107e5e1940 --- /dev/null +++ b/test/Backtracing/TTYDetectionColourLinux.swift @@ -0,0 +1,46 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection +// RUN: %target-codesign %t/TTYDetection + +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run script -ef %t/script-output -- %t/TTYDetection || true) && cat %t/script-output | %FileCheck %s + + +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime +// UNSUPPORTED: asan +// REQUIRES: executable_test +// REQUIRES: backtracing +// REQUIRES: OS=linux-gnu +// COM: this won't work on Windows, but is not critical function + +func level1() { + level2() +} + +func level2() { + level3() +} + +func level3() { + level4() +} + +func level4() { + level5() +} + +func level5() { + print("About to crash") + let ptr = UnsafeMutablePointer(bitPattern: 4)! + ptr.pointee = 42 +} + +@main +struct TTYDetection { + static func main() { + level1() + } +} + +// CHECK: 💣{{.*}}Program crashed: Bad pointer dereference at 0x{{0+}}4 +// CHECK: Thread 0 {{(".*" )?}}crashed: diff --git a/test/Backtracing/TTYDetectionColourMacOS.swift b/test/Backtracing/TTYDetectionColourMacOS.swift new file mode 100644 index 0000000000000..fa5af8284872c --- /dev/null +++ b/test/Backtracing/TTYDetectionColourMacOS.swift @@ -0,0 +1,46 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection +// RUN: %target-codesign %t/TTYDetection + +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run script -reF %t/script-output %t/TTYDetection || true) && cat %t/script-output | %FileCheck %s + + +// UNSUPPORTED: use_os_stdlib +// UNSUPPORTED: back_deployment_runtime +// UNSUPPORTED: asan +// REQUIRES: executable_test +// REQUIRES: backtracing +// REQUIRES: OS=macosx +// COM: this won't work on Windows, but is not critical function + +func level1() { + level2() +} + +func level2() { + level3() +} + +func level3() { + level4() +} + +func level4() { + level5() +} + +func level5() { + print("About to crash") + let ptr = UnsafeMutablePointer(bitPattern: 4)! + ptr.pointee = 42 +} + +@main +struct TTYDetection { + static func main() { + level1() + } +} + +// CHECK: 💣{{.*}}Program crashed: Bad pointer dereference at 0x{{0+}}4 +// CHECK: Thread 0 {{(".*" )?}}crashed: From 196804bb36f3840c9a8778f308139102383ba9a8 Mon Sep 17 00:00:00 2001 From: Carl Peto Date: Fri, 14 Nov 2025 18:43:21 +0000 Subject: [PATCH 3/3] Attempt to fix `script` command parameters to match Ubuntu 24.04.3 LTS --- test/Backtracing/TTYDetectionColourLinux.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Backtracing/TTYDetectionColourLinux.swift b/test/Backtracing/TTYDetectionColourLinux.swift index 6cf107e5e1940..cbc0fea308766 100644 --- a/test/Backtracing/TTYDetectionColourLinux.swift +++ b/test/Backtracing/TTYDetectionColourLinux.swift @@ -2,7 +2,7 @@ // RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection // RUN: %target-codesign %t/TTYDetection -// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run script -ef %t/script-output -- %t/TTYDetection || true) && cat %t/script-output | %FileCheck %s +// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run script -ef -O %t/script-output %t/TTYDetection || true) && cat %t/script-output | %FileCheck %s // UNSUPPORTED: use_os_stdlib