11
11
import TSCLibc
12
12
import TSCBasic
13
13
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
-
24
14
/// This class can be used by command line tools to install a handler which
25
15
/// should be called when a interrupt signal is delivered to the process.
16
+ @available ( * , deprecated, message: " use DispatchSource instead " )
26
17
public 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
27
27
28
28
/// The thread which waits to be notified when a signal is received.
29
29
let thread : Thread
@@ -35,20 +35,27 @@ public final class InterruptHandler {
35
35
36
36
/// Start watching for interrupt signal and call the handler whenever the signal is received.
37
37
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
+
38
45
// Create a signal handler.
39
- signalHandler = { _ in
46
+ self . signalHandler = { _ in
40
47
// Turn on the interrupt bool.
41
- wasInterruptedLock. withLock {
42
- wasInterrupted = true
48
+ InterruptHandler . wasInterruptedLock. withLock {
49
+ InterruptHandler . wasInterrupted = true
43
50
}
44
51
// Write on pipe to notify the watching thread.
45
52
var byte : UInt8 = 0
46
53
#if os(Windows)
47
54
var bytesWritten : DWORD = 0
48
- WriteFile ( signalWatchingPipe [ 1 ] , & byte, 1 , & bytesWritten, nil )
55
+ WriteFile ( InterruptHandler . signalWatchingPipe [ 1 ] , & byte, 1 , & bytesWritten, nil )
49
56
return true
50
57
#else
51
- write ( signalWatchingPipe [ 1 ] , & byte, 1 )
58
+ write ( InterruptHandler . signalWatchingPipe [ 1 ] , & byte, 1 )
52
59
#endif
53
60
}
54
61
#if os(Windows)
@@ -57,25 +64,25 @@ public final class InterruptHandler {
57
64
var readPipe : HANDLE ?
58
65
var writePipe : HANDLE ?
59
66
let rv = CreatePipe ( & readPipe, & writePipe, nil , 1 )
60
- signalWatchingPipe = [ readPipe!, writePipe!]
67
+ Self . signalWatchingPipe = [ readPipe!, writePipe!]
61
68
guard rv else {
62
69
throw SystemError . pipe ( Int32 ( GetLastError ( ) ) )
63
70
}
64
71
#else
65
72
var action = sigaction ( )
66
73
#if canImport(Darwin) || os(OpenBSD)
67
- action. __sigaction_u. __sa_handler = signalHandler
74
+ action. __sigaction_u. __sa_handler = self . signalHandler
68
75
#elseif os(Android)
69
- action. sa_handler = signalHandler
76
+ action. sa_handler = self . signalHandler
70
77
#else
71
78
action. __sigaction_handler = unsafeBitCast (
72
- signalHandler,
79
+ self . signalHandler,
73
80
to: sigaction. __Unnamed_union___sigaction_handler. self)
74
81
#endif
75
82
// Install the new handler.
76
- sigaction ( SIGINT, & action, & oldAction)
83
+ sigaction ( SIGINT, & action, & Self . oldAction)
77
84
// Create pipe.
78
- let rv = TSCLibc . pipe ( & signalWatchingPipe)
85
+ let rv = TSCLibc . pipe ( & Self . signalWatchingPipe)
79
86
guard rv == 0 else {
80
87
throw SystemError . pipe ( rv)
81
88
}
@@ -88,16 +95,16 @@ public final class InterruptHandler {
88
95
var buf : Int8 = 0
89
96
#if os(Windows)
90
97
var n : DWORD = 0
91
- ReadFile ( signalWatchingPipe [ 1 ] , & buf, 1 , & n, nil )
98
+ ReadFile ( Self . signalWatchingPipe [ 1 ] , & buf, 1 , & n, nil )
92
99
#else
93
- let n = read ( signalWatchingPipe [ 0 ] , & buf, 1 )
100
+ let n = read ( Self . signalWatchingPipe [ 0 ] , & buf, 1 )
94
101
#endif
95
102
// Pipe closed, nothing to do.
96
103
if n == 0 { break }
97
104
// 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
101
108
return oldValue
102
109
}
103
110
// Terminate all processes if was interrupted.
@@ -106,22 +113,22 @@ public final class InterruptHandler {
106
113
}
107
114
}
108
115
#if os(Windows)
109
- CloseHandle ( signalWatchingPipe [ 0 ] )
116
+ CloseHandle ( Self . signalWatchingPipe [ 0 ] )
110
117
#else
111
- close ( signalWatchingPipe [ 0 ] )
118
+ close ( Self . signalWatchingPipe [ 0 ] )
112
119
#endif
113
120
}
114
121
thread. start ( )
115
122
}
116
123
117
124
deinit {
118
125
#if os(Windows)
119
- SetConsoleCtrlHandler ( signalHandler, false )
126
+ SetConsoleCtrlHandler ( self . signalHandler, false )
120
127
CloseHandle ( signalWatchingPipe [ 1 ] )
121
128
#else
122
129
// 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 ] )
125
132
#endif
126
133
thread. join ( )
127
134
}
0 commit comments