Skip to content

Commit 3b11c20

Browse files
committed
[Backtracing] Add an option to output to stderr.
In CI, it would be better if the backtraces went to stderr rather than stdout, so provide an option for that. rdar://107192120
1 parent 82b3e75 commit 3b11c20

File tree

7 files changed

+229
-103
lines changed

7 files changed

+229
-103
lines changed

docs/Backtracing.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ follows:
9696
| | | only has effect on platforms that have a symbol |
9797
| | | cache that can be controlled by the runtime. |
9898
+-----------------+---------+--------------------------------------------------+
99+
| output-to | stdout | Set to ``stderr`` to send the backtrace to the |
100+
| | | standard error instead of standard output. This |
101+
| | | may be useful in some CI systems. |
102+
+-----------------+---------+--------------------------------------------------+
99103
| swift-backtrace | | If specified, gives the full path to the |
100104
| | | swift-backtrace binary to use for crashes. |
101105
| | | Otherwise, Swift will locate the binary relative |

include/swift/Runtime/Backtrace.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ enum class SanitizePaths {
9797
On = 1
9898
};
9999

100+
enum class OutputTo {
101+
Stdout = 0,
102+
Stderr = 2,
103+
};
104+
100105
struct BacktraceSettings {
101106
UnwindAlgorithm algorithm;
102107
OnOffTty enabled;
@@ -112,6 +117,7 @@ struct BacktraceSettings {
112117
SanitizePaths sanitize;
113118
Preset preset;
114119
bool cache;
120+
OutputTo outputTo;
115121
const char *swiftBacktracePath;
116122
};
117123

stdlib/public/libexec/swift-backtrace/Target.swift

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class Target {
165165
do {
166166
crashInfo = try reader.fetch(from: crashInfoAddr, as: CrashInfo.self)
167167
} catch {
168-
print("swift-backtrace: unable to fetch crash info.")
168+
print("swift-backtrace: unable to fetch crash info.", to: &standardError)
169169
exit(1)
170170
}
171171

@@ -175,7 +175,7 @@ class Target {
175175

176176
guard let mctx: MContext = try? reader.fetch(from: crashInfo.mctx,
177177
as: MContext.self) else {
178-
print("swift-backtrace: unable to fetch mcontext.")
178+
print("swift-backtrace: unable to fetch mcontext.", to: &standardError)
179179
exit(1)
180180
}
181181

@@ -195,12 +195,13 @@ class Target {
195195
&threadCount)
196196

197197
if kr != KERN_SUCCESS {
198-
print("swift-backtrace: failed to enumerate threads - \(kr)")
198+
print("swift-backtrace: failed to enumerate threads - \(kr)",
199+
to: &standardError)
199200
exit(1)
200201
}
201202

202203
guard let ports = threadPorts else {
203-
print("swift-backtrace: thread array is nil")
204+
print("swift-backtrace: thread array is nil", to: &standardError)
204205
exit(1)
205206
}
206207

@@ -209,12 +210,13 @@ class Target {
209210
var kr = mach_thread_info(ports[Int(ndx)], THREAD_IDENTIFIER_INFO,
210211
&threadIdInfo)
211212
if kr != KERN_SUCCESS {
212-
print("swift-backtrace: unable to get thread info for thread \(ndx) - \(kr)")
213+
print("swift-backtrace: unable to get thread info for thread \(ndx) - \(kr)",
214+
to: &standardError)
213215
exit(1)
214216
}
215217

216218
guard let info = threadIdInfo else {
217-
print("swift-backtrace: thread info is nil")
219+
print("swift-backtrace: thread info is nil", to: &standardError)
218220
exit(1)
219221
}
220222

@@ -228,7 +230,8 @@ class Target {
228230
if kr == KERN_SUCCESS {
229231
threadName = extInfo.pth_swiftName
230232
} else {
231-
print("unable to fetch ext info \(kr)")
233+
print("swift-backtrace: unable to fetch ext info \(kr)",
234+
to: &standardError)
232235
threadName = ""
233236
}
234237

@@ -250,14 +253,16 @@ class Target {
250253
using: reader,
251254
limit: limit,
252255
top: top) else {
253-
print("unable to capture backtrace from context for thread \(ndx)")
256+
print("swift-backtrace: unable to capture backtrace from context for thread \(ndx)",
257+
to: &standardError)
254258
exit(1)
255259
}
256260

257261
guard let symbolicated = backtrace.symbolicated(with: images,
258262
sharedCacheInfo: sharedCacheInfo,
259263
useSymbolCache: cache) else {
260-
print("unable to symbolicate backtrace from context for thread \(ndx)")
264+
print("unable to symbolicate backtrace from context for thread \(ndx)",
265+
to: &standardError)
261266
exit(1)
262267
}
263268

@@ -280,14 +285,16 @@ class Target {
280285
using: reader,
281286
limit: limit,
282287
top: top) else {
283-
print("unable to capture backtrace from context for thread \(ndx)")
288+
print("swift-backtrace: unable to capture backtrace from context for thread \(ndx)",
289+
to: &standardError)
284290
continue
285291
}
286292

287293
guard let symbolicated = backtrace.symbolicated(with: images,
288294
sharedCacheInfo: sharedCacheInfo,
289295
useSymbolCache: cache) else {
290-
print("unable to symbolicate backtrace from context for thread \(ndx)")
296+
print("swift-backtrace: unable to symbolicate backtrace from context for thread \(ndx)",
297+
to: &standardError)
291298
continue
292299
}
293300

stdlib/public/libexec/swift-backtrace/Utils.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,19 @@ internal func spawn(_ path: String, args: [String]) throws {
139139
}
140140
}
141141

142+
struct CFileStream: TextOutputStream {
143+
var fp: UnsafeMutablePointer<FILE>
144+
145+
public func write(_ string: String) {
146+
fputs(string, fp)
147+
}
148+
149+
public func flush() {
150+
fflush(fp)
151+
}
152+
}
153+
154+
var standardOutput = CFileStream(fp: stdout)
155+
var standardError = CFileStream(fp: stderr)
156+
142157
#endif // os(macOS)

0 commit comments

Comments
 (0)