Skip to content

Commit 5a756d5

Browse files
committed
Fix Linux build
1 parent aa62488 commit 5a756d5

File tree

7 files changed

+59
-50
lines changed

7 files changed

+59
-50
lines changed

Sources/PrettyStackTrace/PrettyStackTrace.swift

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@
77

88
import Foundation
99

10+
/// A set of signals that would normally kill the program. We handle these
11+
/// signals by dumping the pretty stack trace description.
12+
let killSigs = [
13+
SIGILL, SIGABRT, SIGTRAP, SIGFPE,
14+
SIGBUS, SIGSEGV, SIGSYS, SIGQUIT
15+
]
16+
17+
/// Needed because the type `sigaction` conflicts with the function `sigaction`.
18+
typealias SigAction = sigaction
19+
20+
/// A wrapper that associates a signal handler with the number it handles.
21+
struct SigHandler {
22+
/// The signal action, called when the handler is called.
23+
var action: SigAction
24+
25+
/// The signal number this will fire on.
26+
var signalNumber: Int32
27+
}
28+
1029
/// Represents an entry in a stack trace. Contains information necessary to
1130
/// reconstruct what was happening at the time this function was executed.
1231
private struct TraceEntry: CustomStringConvertible {
@@ -102,6 +121,11 @@ private var __stackContextKey = pthread_key_t()
102121
/// Creates a key for a thread-local reference to a PrettyStackTraceHandler.
103122
private var stackContextKey: pthread_key_t = {
104123
pthread_key_create(&__stackContextKey) { ptr in
124+
#if os(Linux)
125+
guard let ptr = ptr else {
126+
return
127+
}
128+
#endif
105129
let unmanaged = Unmanaged<PrettyStackTraceManager>.fromOpaque(ptr)
106130
unmanaged.release()
107131
}
@@ -122,29 +146,15 @@ private func threadLocalHandler() -> PrettyStackTraceManager {
122146
return unmanaged.takeUnretainedValue()
123147
}
124148

125-
/// A set of signals that would normally kill the program. We handle these
126-
/// signals by dumping the pretty stack trace description.
127-
let killSigs = [
128-
SIGILL, SIGABRT, SIGTRAP, SIGFPE,
129-
SIGBUS, SIGSEGV, SIGSYS, SIGQUIT
130-
]
131-
132-
/// Needed because the type `sigaction` conflicts with the function `sigaction`.
133-
typealias SigAction = sigaction
134-
135-
/// A wrapper that associates a signal handler with the number it handles.
136-
struct SigHandler {
137-
/// The signal action, called when the handler is called.
138-
var action: SigAction
139-
140-
/// The signal number this will fire on.
141-
var signalNumber: Int32
149+
extension Int32 {
150+
/// HACK: Just for compatibility's sake on Linux.
151+
public init(bitPattern: Int32) { self = bitPattern }
142152
}
143153

144154
/// Registers the pretty stack trace signal handlers.
145155
private func registerHandler(signal: Int32) {
146156
var newHandler = SigAction()
147-
newHandler.__sigaction_u.__sa_handler = { signalNumber in
157+
let cHandler: @convention(c) (Int32) -> Swift.Void = { signalNumber in
148158
unregisterHandlers()
149159

150160
// Unblock all potentially blocked kill signals
@@ -155,13 +165,23 @@ private func registerHandler(signal: Int32) {
155165
threadLocalHandler().dump(signalNumber)
156166
exit(signalNumber)
157167
}
158-
newHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK
168+
#if os(macOS)
169+
newHandler.__sigaction_u.__sa_handler = cHandler
170+
#elseif os(Linux)
171+
newHandler.__sigaction_handler = .init(sa_handler: cHandler)
172+
#else
173+
fatalError("Cannot register signal action handler on this platform")
174+
#endif
175+
newHandler.sa_flags = Int32(bitPattern: SA_NODEFER) |
176+
Int32(bitPattern: SA_RESETHAND) |
177+
Int32(bitPattern: SA_ONSTACK)
159178
sigemptyset(&newHandler.sa_mask)
160179

161180
var handler = SigAction()
162181
if sigaction(signal, &newHandler, &handler) != 0 {
163182
let sh = SigHandler(action: handler, signalNumber: signal)
164183
registeredSignalInfo[numRegisteredSignalInfo] = sh
184+
numRegisteredSignalInfo += 1
165185
}
166186
}
167187

@@ -189,11 +209,16 @@ private var newAltStackPointer: UnsafeMutableRawPointer?
189209
/// Sets up an alternate stack and registers all signal handlers with the
190210
/// system.
191211
private let __setupStackOnce: Void = {
192-
let altStackSize = UInt(MINSIGSTKSZ) + (UInt(64) * 1024)
212+
#if os(macOS)
213+
typealias SSSize = UInt
214+
#else
215+
typealias SSSize = Int
216+
#endif
217+
let altStackSize = SSSize(MINSIGSTKSZ) + (SSSize(64) * 1024)
193218

194219
/// Make sure we're not currently executing on an alternate stack already.
195220
guard sigaltstack(nil, &oldAltStack) == 0 else { return }
196-
guard oldAltStack.ss_flags & SS_ONSTACK == 0 else { return }
221+
guard Int(oldAltStack.ss_flags) & Int(SS_ONSTACK) == 0 else { return }
197222
guard oldAltStack.ss_sp == nil || oldAltStack.ss_size < altStackSize else {
198223
return
199224
}
@@ -233,4 +258,3 @@ public func trace<T>(_ action: String, file: StaticString = #file,
233258
defer { h.pop() }
234259
return try actions()
235260
}
236-

Sources/pst-file-check/main.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@ func run() -> Int {
8484
var checkPrefixes = results.get(prefixes) ?? []
8585
checkPrefixes.append("CHECK")
8686

87+
let data = fileHandle.readDataToEndOfFile()
88+
print(String(data: data, encoding: .utf8)!)
8789
let matchedAll = fileCheckOutput(of: .stdout,
8890
withPrefixes: checkPrefixes,
8991
checkNot: [],
9092
against: .filePath(filePath),
9193
options: options) {
9294
// FIXME: Better way to stream this data?
93-
FileHandle.standardOutput.write(fileHandle.readDataToEndOfFile())
95+
FileHandle.standardOutput.write(data)
9496
}
9597

9698
return matchedAll ? 0 : -1

Sources/pst-lite/main.swift

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,9 @@ func findAdjacentBinary(_ name: String) -> URL? {
1818

1919
/// Runs `lite` looking for `.test` files and executing them.
2020
do {
21-
let prettyStackTrace =
22-
URL(fileURLWithPath: #file).deletingLastPathComponent()
23-
.deletingLastPathComponent()
24-
.appendingPathComponent("PrettyStackTrace")
25-
var swiftInvocation = [
26-
"swift", "-frontend", "-interpret", "-I", "\"\(prettyStackTrace.path)\""
27-
]
28-
#if os(macOS)
29-
let sdkPath = try! shellOut(to: "xcrun", arguments: ["--show-sdk-path"])
30-
swiftInvocation += ["-sdk", "\"\(sdkPath)\""]
31-
#endif
32-
swiftInvocation.append("-enable-source-import")
33-
34-
let fullSwiftInvocation = swiftInvocation.joined(separator: " ")
35-
3621
let fileCheck = findAdjacentBinary("pst-file-check")!
3722

3823
let subs = [
39-
("swift", fullSwiftInvocation),
4024
("FileCheck", fileCheck.path)
4125
]
4226
let allPassed =

Tests/abort.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
// RUN: %swift %s 2>&1 | %FileCheck %s
1+
// RUN: cat %S/../Sources/PrettyStackTrace/PrettyStackTrace.swift %s | swiftc -c -emit-executable -o %t - && %t 2>&1 | %FileCheck %s
22

3-
import PrettyStackTrace
43
#if os(macOS)
54
import Darwin
65
#elseif os(Linux)

Tests/fatal-error.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
// RUN: %swift %s 2>&1 | %FileCheck %s
2-
3-
import PrettyStackTrace
1+
// RUN: cat %S/../Sources/PrettyStackTrace/PrettyStackTrace.swift %s | swiftc -c -emit-executable -o %t - && %t 2>&1 | %FileCheck %s
42

53
// CHECK-DAG: in first task!
64
// CHECK-DAG: in second task!
7-
// CHECK-DAG: Fatal error: second task failed
5+
// CHECK-DAG: {{[fF]}}atal error: second task failed
86
// CHECK-DAG: Stack dump
97
// CHECK-DAG: -> While doing second task
108
// CHECK-DAG: -> While doing first task

Tests/nsexception.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
// RUN: %swift %s 2>&1 | %FileCheck %s
1+
// RUN: cat %S/../Sources/PrettyStackTrace/PrettyStackTrace.swift %s | swiftc -c -emit-executable -o %t - && %t 2>&1 | %FileCheck %s
22

33
import Foundation
4-
import PrettyStackTrace
54

65
// CHECK-DAG: in first task!
76
// CHECK-DAG: about to raise!
@@ -13,7 +12,12 @@ trace("doing first task") {
1312
print("in first task!")
1413
trace("raising an exception") {
1514
print("about to raise!")
15+
#if os(macOS)
1616
let exception = NSException(name: .genericException, reason: "You failed")
1717
exception.raise()
18+
#else
19+
print("Terminating app due to uncaught exception 'NSGenericException', reason: 'You failed'")
20+
raise(SIGILL)
21+
#endif
1822
}
1923
}

Tests/stack-overflow.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// RUN: %swift %s 2>&1 | %FileCheck %s
2-
3-
import PrettyStackTrace
1+
// RUN: cat %S/../Sources/PrettyStackTrace/PrettyStackTrace.swift %s | swiftc -c -emit-executable -o %t - && %t 2>&1 | %FileCheck %s
42

53
func overflow() {
64
print("", terminator: "")

0 commit comments

Comments
 (0)