@@ -116,51 +116,72 @@ class ProcessTests: XCTestCase {
116
116
117
117
#if !os(Windows) // Signals are not supported in Windows
118
118
func testSignals( ) throws {
119
+ let group = DispatchGroup ( )
119
120
120
- // Test sigint terminates the script.
121
- try testWithTemporaryDirectory { tmpdir in
122
- let file = tmpdir. appending ( component: " pidfile " )
123
- let waitFile = tmpdir. appending ( component: " waitFile " )
124
- let process = Process ( args: script ( " print-pid " ) , file. pathString, waitFile. pathString)
125
- try process. launch ( )
126
- guard waitForFile ( waitFile) else {
127
- return XCTFail ( " Couldn't launch the process " )
121
+ DispatchQueue . global ( ) . async ( group: group) {
122
+ do {
123
+ // Test sigint terminates the script.
124
+ try testWithTemporaryDirectory { tmpdir in
125
+ let file = tmpdir. appending ( component: " pidfile " )
126
+ let waitFile = tmpdir. appending ( component: " waitFile " )
127
+ let process = Process ( args: self . script ( " print-pid " ) , file. pathString, waitFile. pathString)
128
+ try process. launch ( )
129
+ guard waitForFile ( waitFile) else {
130
+ return XCTFail ( " Couldn't launch the process " )
131
+ }
132
+ // Ensure process has started running.
133
+ guard try Process . running ( process. processID) else {
134
+ return XCTFail ( " Couldn't launch the process " )
135
+ }
136
+ process. signal ( SIGINT)
137
+ try process. waitUntilExit ( )
138
+ // Ensure the process's pid was written.
139
+ let contents = try localFileSystem. readFileContents ( file) . description
140
+ XCTAssertEqual ( " \( process. processID) " , contents)
141
+ XCTAssertFalse ( try Process . running ( process. processID) )
142
+ }
143
+ } catch {
144
+ XCTFail ( " \( error) " )
128
145
}
129
- // Ensure process has started running.
130
- XCTAssertTrue ( try Process . running ( process. processID) )
131
- process. signal ( SIGINT)
132
- try process. waitUntilExit ( )
133
- // Ensure the process's pid was written.
134
- let contents = try localFileSystem. readFileContents ( file) . description
135
- XCTAssertEqual ( " \( process. processID) " , contents)
136
- XCTAssertFalse ( try Process . running ( process. processID) )
137
146
}
138
147
139
148
// Test SIGKILL terminates the subprocess and any of its subprocess.
140
- try testWithTemporaryDirectory { tmpdir in
141
- let file = tmpdir. appending ( component: " pidfile " )
142
- let waitFile = tmpdir. appending ( component: " waitFile " )
143
- let process = Process ( args: script ( " subprocess " ) , file. pathString, waitFile. pathString)
144
- try process. launch ( )
145
- guard waitForFile ( waitFile) else {
146
- return XCTFail ( " Couldn't launch the process " )
147
- }
148
- // Ensure process has started running.
149
- XCTAssertTrue ( try Process . running ( process. processID) )
150
- process. signal ( SIGKILL)
151
- let result = try process. waitUntilExit ( )
152
- XCTAssertEqual ( result. exitStatus, . signalled( signal: SIGKILL) )
153
- let json = try JSON ( bytes: localFileSystem. readFileContents ( file) )
154
- guard case let . dictionary( dict) = json,
155
- case let . int( parent) ? = dict [ " parent " ] ,
156
- case let . int( child) ? = dict [ " child " ] else {
157
- return XCTFail ( " Couldn't launch the process " )
149
+ DispatchQueue . global ( ) . async ( group: group) {
150
+ do {
151
+ try testWithTemporaryDirectory { tmpdir in
152
+ let file = tmpdir. appending ( component: " pidfile " )
153
+ let waitFile = tmpdir. appending ( component: " waitFile " )
154
+ let process = Process ( args: self . script ( " subprocess " ) , file. pathString, waitFile. pathString)
155
+ try process. launch ( )
156
+ guard waitForFile ( waitFile) else {
157
+ return XCTFail ( " Couldn't launch the process " )
158
+ }
159
+ // Ensure process has started running.
160
+ guard try Process . running ( process. processID) else {
161
+ return XCTFail ( " Couldn't launch the process " )
162
+ }
163
+ process. signal ( SIGKILL)
164
+ let result = try process. waitUntilExit ( )
165
+ XCTAssertEqual ( result. exitStatus, . signalled( signal: SIGKILL) )
166
+ let json = try JSON ( bytes: localFileSystem. readFileContents ( file) )
167
+ guard case let . dictionary( dict) = json,
168
+ case let . int( parent) ? = dict [ " parent " ] ,
169
+ case let . int( child) ? = dict [ " child " ] else {
170
+ return XCTFail ( " Couldn't launch the process " )
171
+ }
172
+ XCTAssertEqual ( process. processID, ProcessID ( parent) )
173
+ // We should have killed the process and any subprocess spawned by it.
174
+ XCTAssertFalse ( try Process . running ( ProcessID ( parent) ) )
175
+ // FIXME: The child process becomes defunct when executing the tests using docker directly without entering the bash.
176
+ XCTAssertFalse ( try Process . running ( ProcessID ( child) , orDefunct: true ) )
177
+ }
178
+ } catch {
179
+ XCTFail ( " \( error) " )
158
180
}
159
- XCTAssertEqual ( process. processID, ProcessID ( parent) )
160
- // We should have killed the process and any subprocess spawned by it.
161
- XCTAssertFalse ( try Process . running ( ProcessID ( parent) ) )
162
- // FIXME: The child process becomes defunct when executing the tests using docker directly without entering the bash.
163
- XCTAssertFalse ( try Process . running ( ProcessID ( child) , orDefunct: true ) )
181
+ }
182
+
183
+ if case . timedOut = group. wait ( timeout: . now( ) + 1 ) {
184
+ XCTFail ( " timeout waiting for signals to be processed " )
164
185
}
165
186
}
166
187
#endif
0 commit comments