8000 Improve error reporting when spawning child process fails · reactphp/child-process@1e10d48 · GitHub 8000
[go: up one dir, main page]

Skip to content

Commit 1e10d48

Browse files
committed
Improve error reporting when spawning child process fails
Suppress PHP warnings on error and report any error message as part of exception messages as expected.
1 parent 1106c24 commit 1e10d48

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/Process.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,11 @@ public function start(LoopInterface $loop, $interval = 0.1)
189189
$options['suppress_errors'] = true;
190190
}
191191

192-
$this->process = \proc_open($cmd, $fdSpec, $pipes, $this->cwd, $this->env, $options);
192+
$this->process = @\proc_open($cmd, $fdSpec, $pipes, $this->cwd, $this->env, $options);
193193

194194
if (!\is_resource($this->process)) {
195-
throw new \RuntimeException('Unable to launch a new process.');
195+
$error = \error_get_last();
196+
throw new \RuntimeException('Unable to launch a new process: ' . $error['message']);
196197
}
197198

198199
// count open process pipes and await close event for each to drain buffers before detecting exit

tests/AbstractProcessTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,52 @@ public function testStartWithCustomPipesWillAssignPipes()
8484
$this->assertInstanceOf('React\Stream\WritableStreamInterface', $process->pipes[3]);
8585
}
8686

87+
/**
88+
* @expectedException RuntimeException
89+
* @expectedExceptionMessage No such file or directory
90+
*/
91+
public function testStartWithInvalidFileDescriptorPathWillThrow()
92+
{
93+
$fds = array(
94+
4 => array('file', '/dev/does-not-exist', 'r')
95+
);
96+
97+
$process = new Process('exit 0', null, null, $fds);
98+
$process->start($this->createLoop());
99+
}
100+
101+
public function testStartWithExcessiveNumberOfFileDescriptorsWillThrow()
102+
{
103+
$ulimit = exec('ulimit -n 2>&1');
104+
if ($ulimit < 1) {
105+
$this->markTestSkipped('Unable to determine limit of open files (ulimit not available?)');
106+
}
107+
108+
$loop = $this->createLoop();
109+
110+
// create 70% (usually ~700) dummy file handles in this parent dummy
111+
$limit = (int)($ulimit * 0.7);
112+
$fds = array();
113+
for ($i = 0; $i < $limit; ++$i) {
114+
$fds[$i] = fopen('/dev/null', 'r');
115+
}
116+
117+
// try to create child process with another ~700 dummy file handles
118+
$new = array_fill(0, $limit, array('file', '/dev/null', 'r'));
119+
$process = new Process('ping example.com', null, null, $new);
120+
121+
try {
122+
$process->start($loop);
123+
124+
$this->fail('Did not expect to reach this point');
125+
} catch (\RuntimeException $e) {
126+
// clear dummy files handles to make some room again (avoid fatal errors for autoloader)
127+
$fds = array();
128+
129+
$this->assertContains('Too many open files', $e->getMessage());
130+
}
131+
}
132+
87133
public function testIsRunning()
88134
{
89135
if (DIRECTORY_SEPARATOR === '\\') {

0 commit comments

Comments
 (0)
0