Skip to content

Commit dcaddcc

Browse files
authored
Merge pull request #14 from clue-labs/race
Avoid race condition for forked process in test suite
2 parents d87d8e4 + f44922d commit dcaddcc

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

tests/FunctionalSshProcessConnectorTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,20 @@ public function testConnectPendingWillNotInheritActiveFileDescriptors()
8888
// close server and ensure we can start a new server on the previous address
8989
// the pending SSH connection process should not inherit the existing server socket
9090
fclose($server);
91-
$server = stream_socket_server('tcp://' . $address);
91+
92+
$server = @stream_socket_server('tcp://' . $address);
93+
if ($server === false) {
94+
// There's a very short race condition where the forked php process
95+
// first has to `dup()` the file descriptor specs before invoking
96+
// `exec()` to switch to the actual `ssh` child process. We don't
97+
// need to wait for the child process to be ready, but only for the
98+
// forked process to close the file descriptors. This happens ~80%
99+
// of times on single core machines and almost never on multi core
100+
// systems, so simply wait 5ms (plenty of time!) and retry again.
101+
usleep(5000);
102+
$server = stream_socket_server('tcp://' . $address);
103+
}
104+
92105
$this->assertTrue(is_resource($server));
93106
fclose($server);
94107

tests/FunctionalSshSocksConnectorTest.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,25 @@ public function testConnectPendingWillNotInheritActiveFileDescriptors()
108108
// close server and ensure we can start a new server on the previous address
109109
// the pending SSH connection process should not inherit the existing server socket
110110
fclose($server);
111-
$server = stream_socket_server('tcp://' . $address);
111+
112+
$server = @stream_socket_server('tcp://' . $address);
113+
if ($server === false) {
114+
// There's a very short race condition where the forked php process
115+
// first has to `dup()` the file descriptor specs before invoking
116+
// `exec()` to switch to the actual `ssh` child process. We don't
117+
// need to wait for the child process to be ready, but only for the
118+
// forked process to close the file descriptors. This happens ~80%
119+
// of times on single core machines and almost never on multi core
120+
// systems, so simply wait 5ms (plenty of time!) and retry again twice.
121+
usleep(5000);
122+
$server = @stream_socket_server('tcp://' . $address);
123+
124+
if ($server === false) {
125+
usleep(5000);
126+
$server = stream_socket_server('tcp://' . $address);
127+
}
128+
}
129+
112130
$this->assertTrue(is_resource($server));
113131
fclose($server);
114132

0 commit comments

Comments
 (0)