7
7
8
8
import Foundation
9
9
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
+
10
29
/// Represents an entry in a stack trace. Contains information necessary to
11
30
/// reconstruct what was happening at the time this function was executed.
12
31
private struct TraceEntry : CustomStringConvertible {
@@ -102,6 +121,11 @@ private var __stackContextKey = pthread_key_t()
102
121
/// Creates a key for a thread-local reference to a PrettyStackTraceHandler.
103
122
private var stackContextKey : pthread_key_t = {
104
123
pthread_key_create ( & __stackContextKey) { ptr in
124
+ #if os(Linux)
125
+ guard let ptr = ptr else {
126
+ return
127
+ }
128
+ #endif
105
129
let unmanaged = Unmanaged< PrettyStackTraceManager> . fromOpaque( ptr)
106
130
unmanaged. release ( )
107
131
}
@@ -122,29 +146,15 @@ private func threadLocalHandler() -> PrettyStackTraceManager {
122
146
return unmanaged. takeUnretainedValue ( )
123
147
}
124
148
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 }
142
152
}
143
153
144
154
/// Registers the pretty stack trace signal handlers.
145
155
private func registerHandler( signal: Int32 ) {
146
156
var newHandler = SigAction ( )
147
- newHandler . __sigaction_u . __sa_handler = { signalNumber in
157
+ let cHandler : @ convention ( c ) ( Int32 ) -> Swift . Void = { signalNumber in
148
158
unregisterHandlers ( )
149
159
150
160
// Unblock all potentially blocked kill signals
@@ -155,13 +165,23 @@ private func registerHandler(signal: Int32) {
155
165
threadLocalHandler ( ) . dump ( signalNumber)
156
166
exit ( signalNumber)
157
167
}
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)
159
178
sigemptyset ( & newHandler. sa_mask)
160
179
161
180
var handler = SigAction ( )
162
181
if sigaction ( signal, & newHandler, & handler) != 0 {
163
182
let sh = SigHandler ( action: handler, signalNumber: signal)
164
183
registeredSignalInfo [ numRegisteredSignalInfo] = sh
184
+ numRegisteredSignalInfo += 1
165
185
}
166
186
}
167
187
@@ -189,11 +209,16 @@ private var newAltStackPointer: UnsafeMutableRawPointer?
189
209
/// Sets up an alternate stack and registers all signal handlers with the
190
210
/// system.
191
211
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 )
193
218
194
219
/// Make sure we're not currently executing on an alternate stack already.
195
220
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 }
197
222
guard oldAltStack. ss_sp == nil || oldAltStack. ss_size < altStackSize else {
198
223
return
199
224
}
@@ -233,4 +258,3 @@ public func trace<T>(_ action: String, file: StaticString = #file,
233
258
defer { h. pop ( ) }
234
259
return try actions ( )
235
260
}
236
-
0 commit comments