1111import TSCLibc
1212import TSCBasic
1313
14- /// Interrupt signal handling global variables
15- private var wasInterrupted = false
16- private var wasInterruptedLock = Lock ( )
17- #if os(Windows)
18- private var signalWatchingPipe : [ HANDLE ] = [ INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE]
19- #else
20- private var signalWatchingPipe : [ Int32 ] = [ 0 , 0 ]
21- private var oldAction = sigaction ( )
22- #endif
23-
2414/// This class can be used by command line tools to install a handler which
2515/// should be called when a interrupt signal is delivered to the process.
16+ @available ( * , deprecated, message: " use DispatchSource instead " )
2617public final class InterruptHandler {
18+ /// Interrupt signal handling global variables
19+ private static var wasInterrupted = false
20+ private static var wasInterruptedLock = Lock ( )
21+ #if os(Windows)
22+ private static var signalWatchingPipe : [ HANDLE ] = [ INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE]
23+ #else
24+ private static var signalWatchingPipe : [ Int32 ] = [ 0 , 0 ]
25+ private static var oldAction = sigaction ( )
26+ #endif
2727
2828 /// The thread which waits to be notified when a signal is received.
2929 let thread : Thread
@@ -35,20 +35,27 @@ public final class InterruptHandler {
3535
3636 /// Start watching for interrupt signal and call the handler whenever the signal is received.
3737 public init ( _ handler: @escaping ( ) -> Void ) throws {
38+ // Swift reserves the right to lazily-initialize globals & statics
39+ // force initialize the statics so they as signal-safe
40+ _ = Self . wasInterrupted
41+ _ = Self . wasInterruptedLock
42+ _ = Self . signalWatchingPipe
43+ _ = Self . oldAction
44+
3845 // Create a signal handler.
39- signalHandler = { _ in
46+ self . signalHandler = { _ in
4047 // Turn on the interrupt bool.
41- wasInterruptedLock. withLock {
42- wasInterrupted = true
48+ InterruptHandler . wasInterruptedLock. withLock {
49+ InterruptHandler . wasInterrupted = true
4350 }
4451 // Write on pipe to notify the watching thread.
4552 var byte : UInt8 = 0
4653 #if os(Windows)
4754 var bytesWritten : DWORD = 0
48- WriteFile ( signalWatchingPipe [ 1 ] , & byte, 1 , & bytesWritten, nil )
55+ WriteFile ( InterruptHandler . signalWatchingPipe [ 1 ] , & byte, 1 , & bytesWritten, nil )
4956 return true
5057 #else
51- write ( signalWatchingPipe [ 1 ] , & byte, 1 )
58+ write ( InterruptHandler . signalWatchingPipe [ 1 ] , & byte, 1 )
5259 #endif
5360 }
5461 #if os(Windows)
@@ -57,25 +64,25 @@ public final class InterruptHandler {
5764 var readPipe : HANDLE ?
5865 var writePipe : HANDLE ?
5966 let rv = CreatePipe ( & readPipe, & writePipe, nil , 1 )
60- signalWatchingPipe = [ readPipe!, writePipe!]
67+ Self . signalWatchingPipe = [ readPipe!, writePipe!]
6168 guard rv else {
6269 throw SystemError . pipe ( Int32 ( GetLastError ( ) ) )
6370 }
6471 #else
6572 var action = sigaction ( )
6673 #if canImport(Darwin) || os(OpenBSD)
67- action. __sigaction_u. __sa_handler = signalHandler
74+ action. __sigaction_u. __sa_handler = self . signalHandler
6875 #elseif os(Android)
69- action. sa_handler = signalHandler
76+ action. sa_handler = self . signalHandler
7077 #else
7178 action. __sigaction_handler = unsafeBitCast (
72- signalHandler,
79+ self . signalHandler,
7380 to: sigaction. __Unnamed_union___sigaction_handler. self)
7481 #endif
7582 // Install the new handler.
76- sigaction ( SIGINT, & action, & oldAction)
83+ sigaction ( SIGINT, & action, & Self . oldAction)
7784 // Create pipe.
78- let rv = TSCLibc . pipe ( & signalWatchingPipe)
85+ let rv = TSCLibc . pipe ( & Self . signalWatchingPipe)
7986 guard rv == 0 else {
8087 throw SystemError . pipe ( rv)
8188 }
@@ -88,16 +95,16 @@ public final class InterruptHandler {
8895 var buf : Int8 = 0
8996 #if os(Windows)
9097 var n : DWORD = 0
91- ReadFile ( signalWatchingPipe [ 1 ] , & buf, 1 , & n, nil )
98+ ReadFile ( Self . signalWatchingPipe [ 1 ] , & buf, 1 , & n, nil )
9299 #else
93- let n = read ( signalWatchingPipe [ 0 ] , & buf, 1 )
100+ let n = read ( Self . signalWatchingPipe [ 0 ] , & buf, 1 )
94101 #endif
95102 // Pipe closed, nothing to do.
96103 if n == 0 { break }
97104 // Read the value of wasInterrupted and set it to false.
98- let wasInt = wasInterruptedLock. withLock { ( ) -> Bool in
99- let oldValue = wasInterrupted
100- wasInterrupted = false
105+ let wasInt = Self . wasInterruptedLock. withLock { ( ) -> Bool in
106+ let oldValue = Self . wasInterrupted
107+ Self . wasInterrupted = false
101108 return oldValue
102109 }
103110 // Terminate all processes if was interrupted.
@@ -106,22 +113,22 @@ public final class InterruptHandler {
106113 }
107114 }
108115 #if os(Windows)
109- CloseHandle ( signalWatchingPipe [ 0 ] )
116+ CloseHandle ( Self . signalWatchingPipe [ 0 ] )
110117 #else
111- close ( signalWatchingPipe [ 0 ] )
118+ close ( Self . signalWatchingPipe [ 0 ] )
112119 #endif
113120 }
114121 thread. start ( )
115122 }
116123
117124 deinit {
118125 #if os(Windows)
119- SetConsoleCtrlHandler ( signalHandler, false )
126+ SetConsoleCtrlHandler ( self . signalHandler, false )
120127 CloseHandle ( signalWatchingPipe [ 1 ] )
121128 #else
122129 // Restore the old action and close the write end of pipe.
123- sigaction ( SIGINT, & oldAction, nil )
124- close ( signalWatchingPipe [ 1 ] )
130+ sigaction ( SIGINT, & Self . oldAction, nil )
131+ close ( Self . signalWatchingPipe [ 1 ] )
125132 #endif
126133 thread. join ( )
127134 }
0 commit comments