Compare commits
9 Commits
tomerd-patch-1
...
1.3.2
| Author | SHA1 | Date | |
|---|---|---|---|
| baf9597d12 | |||
| 7ba397e50d | |||
| ad485ae151 | |||
| 662e436989 | |||
| 923624a26e | |||
| e2621e2fa1 | |||
| ea4824d488 | |||
| f1db8bf93d | |||
| 99a6c79fc5 |
@@ -2,8 +2,14 @@
|
||||
|
||||
This Swift package provides support for automatically printing crash backtraces of Swift programs.
|
||||
|
||||
The library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms.
|
||||
When this gap is closed at the language runtime level, this library will become redundant and be deprecated.
|
||||
|
||||
## Usage
|
||||
|
||||
When building web-services and daemons, direct usage of this library is discouraged.
|
||||
Instead, use [swift-service-lifecycle](https://github.com/swift-server/swift-service-lifecycle) which helps manage the application lifecycle including setting up backtraces hooks when needed.
|
||||
|
||||
Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`.
|
||||
|
||||
### Crash backtraces
|
||||
|
||||
@@ -67,9 +67,9 @@ private func printBacktrace(signal: CInt) {
|
||||
}
|
||||
|
||||
public enum Backtrace {
|
||||
/// Install the backtrace handler on `SIGILL`.
|
||||
/// Install the backtrace handler on default signals: `SIGILL`, `SIGSEGV`, `SIGBUS`, `SIGFPE`.
|
||||
public static func install() {
|
||||
Backtrace.install(signals: [SIGILL])
|
||||
Backtrace.install(signals: [SIGILL, SIGSEGV, SIGBUS, SIGFPE])
|
||||
}
|
||||
|
||||
/// Install the backtrace handler when any of `signals` happen.
|
||||
@@ -77,6 +77,7 @@ public enum Backtrace {
|
||||
for signal in signals {
|
||||
self.setupHandler(signal: signal) { signal in
|
||||
printBacktrace(signal: signal)
|
||||
raise(signal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,28 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Backtrace
|
||||
#if canImport(Darwin)
|
||||
import Darwin
|
||||
#elseif os(Linux)
|
||||
import Glibc
|
||||
#endif
|
||||
|
||||
Backtrace.install()
|
||||
|
||||
func raiseSignal(_ signal: Int32) {
|
||||
raise(signal)
|
||||
}
|
||||
|
||||
let reason = CommandLine.arguments.count == 2 ? CommandLine.arguments[1] : "unknown"
|
||||
Backtrace.install()
|
||||
fatalError(reason)
|
||||
switch reason.uppercased() {
|
||||
case "SIGILL":
|
||||
raiseSignal(SIGILL)
|
||||
case "SIGSEGV":
|
||||
raiseSignal(SIGSEGV)
|
||||
case "SIGBUS":
|
||||
raiseSignal(SIGBUS)
|
||||
case "SIGFPE":
|
||||
raiseSignal(SIGFPE)
|
||||
default:
|
||||
fatalError(reason)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,11 @@ import XCTest
|
||||
extension BacktraceTests {
|
||||
public static var allTests: [(String, (BacktraceTests) -> () throws -> Void)] {
|
||||
return [
|
||||
("testBacktrace", testBacktrace),
|
||||
("testFatalError", testFatalError),
|
||||
("testSIGILL", testSIGILL),
|
||||
("testSIGSEGV", testSIGSEGV),
|
||||
("testSIGBUS", testSIGBUS),
|
||||
("testSIGFPE", testSIGFPE),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,22 +15,76 @@
|
||||
import XCTest
|
||||
|
||||
public final class BacktraceTests: XCTestCase {
|
||||
func testBacktrace() {
|
||||
#if os(Linux)
|
||||
func testFatalError() throws {
|
||||
#if !os(Linux)
|
||||
try XCTSkipIf(true, "test is only supported on Linux")
|
||||
#endif
|
||||
|
||||
let expectedError = UUID().uuidString
|
||||
let stderr = try runSample(reason: expectedError)
|
||||
print(stderr)
|
||||
|
||||
XCTAssert(stderr.contains("Received signal 4. Backtrace:"))
|
||||
XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace")
|
||||
XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information")
|
||||
}
|
||||
|
||||
func testSIGILL() throws {
|
||||
#if !os(Linux)
|
||||
try XCTSkipIf(true, "test is only supported on Linux")
|
||||
#endif
|
||||
|
||||
let stderr = try runSample(reason: "SIGILL")
|
||||
print(stderr)
|
||||
|
||||
XCTAssert(stderr.contains("Received signal \(SIGILL). Backtrace:"))
|
||||
XCTAssert(stderr.contains("Sample.raiseSignal"))
|
||||
}
|
||||
|
||||
func testSIGSEGV() throws {
|
||||
#if !os(Linux)
|
||||
try XCTSkipIf(true, "test is only supported on Linux")
|
||||
#endif
|
||||
|
||||
let stderr = try runSample(reason: "SIGSEGV")
|
||||
print(stderr)
|
||||
|
||||
XCTAssert(stderr.contains("Received signal \(SIGSEGV). Backtrace:"))
|
||||
XCTAssert(stderr.contains("Sample.raiseSignal"))
|
||||
}
|
||||
|
||||
func testSIGBUS() throws {
|
||||
#if !os(Linux)
|
||||
try XCTSkipIf(true, "test is only supported on Linux")
|
||||
#endif
|
||||
|
||||
let stderr = try runSample(reason: "SIGBUS")
|
||||
print(stderr)
|
||||
|
||||
XCTAssert(stderr.contains("Received signal \(SIGBUS). Backtrace:"))
|
||||
XCTAssert(stderr.contains("Sample.raiseSignal"))
|
||||
}
|
||||
|
||||
func testSIGFPE() throws {
|
||||
#if !os(Linux)
|
||||
try XCTSkipIf(true, "test is only supported on Linux")
|
||||
#endif
|
||||
|
||||
let stderr = try runSample(reason: "SIGFPE")
|
||||
print(stderr)
|
||||
|
||||
XCTAssert(stderr.contains("Received signal \(SIGFPE). Backtrace:"))
|
||||
XCTAssert(stderr.contains("Sample.raiseSignal"))
|
||||
}
|
||||
|
||||
func runSample(reason: String) throws -> String {
|
||||
let pipe = Pipe()
|
||||
let process = Process()
|
||||
process.executableURL = URL(fileURLWithPath: "/usr/bin/swift")
|
||||
process.arguments = ["run", "Sample", expectedError]
|
||||
process.arguments = ["run", "Sample", reason]
|
||||
process.standardError = pipe
|
||||
XCTAssertNoThrow(try process.run())
|
||||
if process.isRunning {
|
||||
process.waitUntilExit()
|
||||
}
|
||||
let stderr = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
print(stderr)
|
||||
XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace")
|
||||
XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information")
|
||||
#endif
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
return String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -18,9 +18,9 @@ RUN apt-get update && apt-get install -y lsof dnsutils netcat-openbsd net-tools
|
||||
|
||||
# ruby and jazzy for docs generation
|
||||
RUN apt-get update && apt-get install -y ruby ruby-dev libsqlite3-dev build-essential
|
||||
# switch of gem docs building
|
||||
RUN echo "gem: --no-document" > ~/.gemrc
|
||||
RUN if [ "${ubuntu_version}" != "xenial" ] ; then gem install jazzy ; fi
|
||||
# jazzy no longer works on older version of ubuntu as ruby is too old.
|
||||
RUN if [ "${ubuntu_version}" = "focal" ] ; then echo "gem: --no-document" > ~/.gemrc ; fi
|
||||
RUN if [ "${ubuntu_version}" = "focal" ] ; then gem install jazzy ; fi
|
||||
|
||||
# tools
|
||||
RUN mkdir -p $HOME/.tools
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-linux-backtrace:20.04-5.5
|
||||
build:
|
||||
args:
|
||||
ubuntu_version: "focal"
|
||||
swift_version: "5.5"
|
||||
|
||||
test:
|
||||
image: swift-linux-backtrace:20.04-5.5
|
||||
|
||||
shell:
|
||||
image: swift-linux-backtrace:20.04-5.5
|
||||
@@ -0,0 +1,16 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-linux-backtrace:20.04-5.6
|
||||
build:
|
||||
args:
|
||||
ubuntu_version: "focal"
|
||||
swift_version: "5.6"
|
||||
|
||||
test:
|
||||
image: swift-linux-backtrace:20.04-5.6
|
||||
|
||||
shell:
|
||||
image: swift-linux-backtrace:20.04-5.6
|
||||
@@ -0,0 +1,15 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-linux-backtrace:20.04-5.7
|
||||
build:
|
||||
args:
|
||||
base_image: "swiftlang/swift:nightly-main-focal"
|
||||
|
||||
test:
|
||||
image: swift-linux-backtrace:20.04-5.7
|
||||
|
||||
shell:
|
||||
image: swift-linux-backtrace:20.04-5.7
|
||||
@@ -0,0 +1,15 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
|
||||
runtime-setup:
|
||||
image: swift-linux-backtrace:20.04-main
|
||||
build:
|
||||
args:
|
||||
base_image: "swiftlang/swift:nightly-main-focal"
|
||||
|
||||
test:
|
||||
image: swift-linux-backtrace:20.04-main
|
||||
|
||||
shell:
|
||||
image: swift-linux-backtrace:20.04-main
|
||||
@@ -34,4 +34,4 @@ services:
|
||||
|
||||
shell:
|
||||
<<: *common
|
||||
entrypoint: /bin/bash
|
||||
entrypoint: /bin/bash -l
|
||||
|
||||
Reference in New Issue
Block a user