@@ -76,12 +76,12 @@ class Process
76
76
77
77
private static $ sigchild ;
78
78
private static $ posixSignals = array (
79
- 1 => 1 , // SIGHUP
80
- 2 => 2 , // SIGINT
81
- 3 => 3 , // SIGQUIT
82
- 6 => 6 , // SIGABRT
83
- 14 => 14 , // SIGALRM
84
- 15 => 15 , // SIGTERM
79
+ 1 , // SIGHUP
80
+ 2 , // SIGINT
81
+ 3 , // SIGQUIT
82
+ 6 , // SIGABRT
83
+ 14 , // SIGALRM
84
+ 15 , // SIGTERM
85
85
);
86
86
87
87
/**
@@ -285,27 +285,35 @@ public function start(callable $callback = null)
285
285
if (!isset ($ this ->options ['bypass_shell ' ])) {
286
286
$ this ->options ['bypass_shell ' ] = true ;
287
287
}
288
- }
288
+ } elseif (!$ this ->useFileHandles && $ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
289
+ // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
290
+ $ descriptors [3 ] = array ('pipe ' , 'w ' );
291
+
292
+ $ commandline = '' ;
293
+ foreach (self ::$ posixSignals as $ s ) {
294
+ $ commandline .= "trap 'echo s $ s >&3' $ s; " ;
295
+ }
289
296
290
- $ ptsWorkaround = null ;
297
+ // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
298
+ $ commandline .= '{ ( ' .$ this ->commandline .') <&3 3<&- 3>/dev/null & } 3<&0; ' ;
299
+ $ commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo x$code >&3; exit $code ' ;
291
300
292
- if (!$ this ->useFileHandles && $ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
293
301
// Workaround for the bug, when PTS functionality is enabled.
294
302
// @see : https://bugs.php.net/69442
295
303
$ ptsWorkaround = fopen (__FILE__ , 'r ' );
296
304
}
297
305
298
306
$ this ->process = proc_open ($ commandline , $ descriptors , $ this ->processPipes ->pipes , $ this ->cwd , $ this ->env , $ this ->options );
299
307
300
- if ($ ptsWorkaround ) {
301
- fclose ($ ptsWorkaround );
302
- }
303
-
304
308
if (!is_resource ($ this ->process )) {
305
309
throw new RuntimeException ('Unable to launch a new process. ' );
306
310
}
307
311
$ this ->status = self ::STATUS_STARTED ;
308
312
313
+ if (isset ($ descriptors [3 ])) {
314
+ $ this ->fallbackStatus ['pid ' ] = (int ) fgets ($ this ->processPipes ->pipes [3 ]);
315
+ }
316
+
309
317
if ($ this ->tty ) {
310
318
return ;
311
319
}
@@ -596,8 +604,6 @@ public function clearErrorOutput()
596
604
public function getExitCode ()
597
605
{
598
606
if (!$ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
599
- $ this ->stop (0 );
600
-
601
607
throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method. ' );
602
608
}
603
609
@@ -651,8 +657,6 @@ public function hasBeenSignaled()
651
657
$ this ->requireProcessIsTerminated (__FUNCTION__ );
652
658
653
659
if (!$ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
654
- $ this ->stop (0 );
655
-
656
660
throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. ' );
657
661
}
658
662
@@ -674,8 +678,6 @@ public function getTermSignal()
674
678
$ this ->requireProcessIsTerminated (__FUNCTION__ );
675
679
676
680
if ($ this ->isSigchildEnabled () && (!$ this ->enhanceSigchildCompatibility || -1 === $ this ->processInformation ['termsig ' ])) {
677
- $ this ->stop (0 );
678
-
679
681
throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved. ' );
680
682
}
681
683
@@ -1185,14 +1187,7 @@ public static function isPtySupported()
1185
1187
return $ result = false ;
1186
1188
}
1187
1189
1188
- $ proc = @proc_open ('echo 1 ' , array (array ('pty ' ), array ('pty ' ), array ('pty ' )), $ pipes );
1189
- if (is_resource ($ proc )) {
1190
- proc_close ($ proc );
1191
-
1192
- return $ result = true ;
1193
- }
1194
-
1195
- return $ result = false ;
1190
+ return $ result = (bool ) @proc_open ('echo 1 ' , array (array ('pty ' ), array ('pty ' ), array ('pty ' )), $ pipes );
1196
1191
}
1197
1192
1198
1193
/**
@@ -1207,22 +1202,8 @@ private function getDescriptors()
1207
1202
} else {
1208
1203
$ this ->processPipes = UnixPipes::create ($ this , $ this ->input );
1209
1204
}
1210
- $ descriptors = $ this ->processPipes ->getDescriptors ($ this ->outputDisabled );
1211
-
1212
- if (!$ this ->useFileHandles && $ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
1213
- // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
1214
- $ descriptors [3 ] = array ('pipe ' , 'w ' );
1215
-
1216
- $ trap = '' ;
1217
- foreach (self ::$ posixSignals as $ s ) {
1218
- $ trap .= "trap 'echo s $ s >&3' $ s; " ;
1219
- }
1220
-
1221
- $ this ->commandline = $ trap .'{ ( ' .$ this ->commandline .') <&3 3<&- 3>/dev/null & } 3<&0; ' ;
1222
- $ this ->commandline .= 'pid=$!; echo p$pid >&3; wait $pid; code=$?; echo x$code >&3; exit $code ' ;
1223
- }
1224
1205
1225
- return $ descriptors ;
1206
+ return $ this -> processPipes -> getDescriptors ( $ this -> outputDisabled ) ;
1226
1207
}
1227
1208
1228
1209
/**
@@ -1340,8 +1321,11 @@ private function readPipes($blocking, $close)
1340
1321
$ this ->fallbackStatus ['signaled ' ] = true ;
1341
1322
$ this ->fallbackStatus ['exitcode ' ] = -1 ;
1342
1323
$ this ->fallbackStatus ['termsig ' ] = (int ) substr ($ data , 1 );
1343
- } elseif ('x ' === $ data [0 ] && !isset ($ this ->fallbackStatus ['signaled ' ])) {
1344
- $ this ->fallbackStatus ['exitcode ' ] = (int ) substr ($ data , 1 );
1324
+ } elseif ('x ' === $ data [0 ]) {
1325
+ $ this ->fallbackStatus ['running ' ] = false ;
1326
+ if (!isset ($ this ->fallbackStatus ['signaled ' ])) {
1327
+ $ this ->fallbackStatus ['exitcode ' ] = (int ) substr ($ data , 1 );
1328
+ }
1345
1329
}
1346
1330
}
1347
1331
} else {
@@ -1423,14 +1407,6 @@ private function doSignal($signal, $throwException)
1423
1407
return false ;
1424
1408
}
1425
1409
1426
- if ($ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled () && !isset (self ::$ posixSignals [$ signal ]) && !(function_exists ('posix_kill ' ) && @posix_kill ($ this ->getPid (), $ signal ))) {
1427
- if ($ throwException ) {
1428
- throw new RuntimeException ('This PHP has been compiled with --enable-sigchild and posix_kill() is not available. ' );
1429
- }
1430
-
1431
- return false ;
1432
- }
1433
-
1434
1410
if ('\\' === DIRECTORY_SEPARATOR ) {
1435
1411
exec (sprintf ('taskkill /F /T /PID %d 2>&1 ' , $ this ->getPid ()), $ output , $ exitCode );
1436
1412
if ($ exitCode && $ this ->isRunning ()) {
@@ -1440,14 +1416,21 @@ private function doSignal($signal, $throwException)
1440
1416
1441
1417
return false ;
1442
1418
}
1443
- }
1444
-
1445
- if (true !== @proc_terminate ($ this ->process , $ signal ) && '\\' !== DIRECTORY_SEPARATOR ) {
1446
- if ($ throwException ) {
1447
- throw new RuntimeException (sprintf ('Error while sending signal `%s`. ' , $ signal ));
1419
+ } else {
1420
+ if (!$ this ->enhanceSigchildCompatibility || !$ this ->isSigchildEnabled ()) {
1421
+ $ ok = @proc_terminate ($ this ->process , $ signal );
1422
+ } elseif (function_exists ('posix_kill ' )) {
1423
+ $ ok = @posix_kill ($ this ->getPid (), $ signal );
1424
+ } elseif ($ ok = proc_open (sprintf ('kill -%d %d ' , $ signal , $ this ->getPid ()), array (2 => array ('pipe ' , 'w ' )), $ pipes )) {
1425
+ $ ok = false === fgets ($ pipes [2 ]);
1448
1426
}
1427
+ if (!$ ok ) {
1428
+ if ($ throwException ) {
1429
+ throw new RuntimeException (sprintf ('Error while sending signal `%s`. ' , $ signal ));
1430
+ }
1449
1431
1450
- return false ;
1432
+ return false ;
1433
+ }
1451
1434
}
1452
1435
1453
1436
$ this ->latestSignal = (int ) $ signal ;
0 commit comments