@@ -46,7 +46,7 @@ private struct TraceEntry: CustomStringConvertible {
4646 var description : String {
4747 let base = URL ( fileURLWithPath: file. description) . lastPathComponent
4848 return """
49- -> While \( action) (func \( function) , in file \( base) , line \( line) )
49+ While \( action) (func \( function) , in file \( base) , line \( line) )
5050 """
5151 }
5252}
@@ -59,6 +59,63 @@ var registeredSignalInfo =
5959 count: killSigs. count)
6060var numRegisteredSignalInfo = 0
6161
62+ /// 8 digits + 2 spaces + 1 period + 1 space + 1 NULL terminator
63+ /// ought to be enough for anyone...
64+ let numberBuffer : UnsafeMutablePointer < Int8 > = {
65+ let count = 13
66+ let ptr = UnsafeMutablePointer< Int8> . allocate( capacity: count)
67+
68+ /// NUL terminator
69+ ptr [ count - 1 ] = 0
70+
71+ return ptr
72+ } ( )
73+
74+ /// Fills a pre-allocated 13-byte buffer with the following:
75+ ///
76+ /// [' ', ' ', '1', '2', '3', '4', '5', '6', '7', '8', '.', ' ', '\0']
77+ ///
78+ /// ensuring that the buffer only uses the exact digits from the integer and
79+ /// doesn't write outside the bounds of the buffer.
80+ /// It then writes the contents of this buffer, starting at the first space at
81+ /// the beginning, to stderr.
82+ func writeInt( _ int: UInt ) {
83+ // We can't write more than 8 digits.
84+ guard int <= 99_999_999 else { return }
85+ var int = int
86+
87+ // Fill the buffer from right to left, decrementing the pointer as we add
88+ // characters and digits.
89+
90+ // First, add the '. ' at the end.
91+ var end = numberBuffer. advanced ( by: 12 )
92+ end. pointee = 32 /// (ascii ' ')
93+ end = end. predecessor ( )
94+ end. pointee = 46 /// (ascii '.')
95+ end = end. predecessor ( )
96+
97+ // Next, pop successive digits off the end of the integer and add them to
98+ // the current 'start' of the buffer.
99+ while int > 0 {
100+ let remInt = int. remainderReportingOverflow ( dividingBy: 10 ) . partialValue
101+ let remInt8 = Int8 ( truncatingIfNeeded: remInt)
102+ int = int. unsafeDivided ( by: 10 )
103+ end. pointee = remInt8 &+ 48 /// (ascii '0')
104+ end = end. predecessor ( )
105+ }
106+
107+ // Add the ' ' at the current 'start' of the buffer.
108+ end. pointee = 32 /// (ascii ' ')
109+ end = end. predecessor ( )
110+ end. pointee = 32 /// (ascii ' ')
111+ // Don't move to the predecessor -- we're at the beginning of the string now.
112+
113+ // Find the distance between the end of the buffer and the beginning of our
114+ // string.
115+ let dist = abs ( numberBuffer. advanced ( by: 13 ) . distance ( to: end) )
116+ write ( STDERR_FILENO, end, dist)
117+ }
118+
62119/// A class managing a stack of trace entries. When a particular thread gets
63120/// a kill signal, this handler will dump all the entries in the tack trace and
64121/// end the process.
@@ -84,7 +141,7 @@ private class PrettyStackTraceManager {
84141
85142 /// Pushes the description of a trace entry to the stack.
86143 func push( _ entry: TraceEntry ) {
87- let str = " \( entry. description) \n "
144+ let str = " \( entry. description) \n "
88145 let newEntry = StackEntry ( prev: stack,
89146 data: strndup ( str, str. count) ,
90147 count: str. count)
@@ -106,11 +163,14 @@ private class PrettyStackTraceManager {
106163 /// recent entry.
107164 func dump( _ signal: Int32 ) {
108165 write ( STDERR_FILENO, stackDumpMsg. data, stackDumpMsg. count)
166+ var i : UInt = 1
109167 var cur = stack
110168 while cur != nil {
169+ writeInt ( i)
111170 let entry = cur. unsafelyUnwrapped
112171 write ( STDERR_FILENO, entry. pointee. data, entry. pointee. count)
113172 cur = entry. pointee. prev
173+ i += 1
114174 }
115175 }
116176}
@@ -215,6 +275,9 @@ private let __setupStackOnce: Void = {
215275 #else
216276 typealias SSSize = Int
217277 #endif
278+
279+ _ = numberBuffer
280+
218281 let altStackSize = SSSize ( MINSIGSTKSZ) + ( SSSize ( 64 ) * 1024 )
219282
220283 /// Make sure we're not currently executing on an alternate stack already.
0 commit comments