@@ -47,13 +47,16 @@ class Process
47
47
private $ stdout ;
48
48
private $ stderr ;
49
49
private $ enhanceWindowsCompatibility ;
50
+ private $ enhanceSigchildCompatibility ;
50
51
private $ pipes ;
51
52
private $ process ;
52
53
private $ status = self ::STATUS_READY ;
53
54
54
55
private $ fileHandles ;
55
56
private $ readBytes ;
56
57
58
+ private static $ sigchild ;
59
+
57
60
/**
58
61
* Exit codes translation table.
59
62
*
@@ -137,6 +140,7 @@ public function __construct($commandline, $cwd = null, array $env = null, $stdin
137
140
$ this ->stdin = $ stdin ;
138
141
$ this ->setTimeout ($ timeout );
139
142
$ this ->enhanceWindowsCompatibility = true ;
143
+ $ this ->enhanceSigchildCompatibility = !defined ('PHP_WINDOWS_VERSION_BUILD ' ) && $ this ->isSigchildEnabled ();
140
144
$ this ->options = array_replace (array ('suppress_errors ' => true , 'binary_pipes ' => true ), $ options );
141
145
}
142
146
@@ -219,9 +223,16 @@ public function start($callback = null)
219
223
array ('pipe ' , 'r ' ), // stdin
220
224
array ('pipe ' , 'w ' ), // stdout
221
225
array ('pipe ' , 'w ' ), // stderr
222
- array ('pipe ' , 'w ' ) // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
223
226
);
224
- $ this ->commandline = '( ' .$ this ->commandline .') 3>/dev/null; code=$?; echo $code >&3; exit $code ' ;
227
+
228
+ if ($ this ->enhanceSigchildCompatibility && $ this ->isSigchildEnabled ()) {
229
+ // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
230
+ $ descriptors = array_merge ($ descriptors , array (array ('pipe ' , 'w ' )));
231
+
232
+ $ this ->commandline = '( ' .$ this ->commandline .') 3>/dev/null; code=$?; echo $code >&3; exit $code ' ;
233
+ } else {
234
+ $ this ->commandline = 'exec ' . $ this ->commandline ;
235
+ }
225
236
}
226
237
227
238
$ commandline = $ this ->commandline ;
@@ -421,10 +432,16 @@ public function getErrorOutput()
421
432
*
422
433
* @return integer The exit status code
423
434
*
435
+ * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
436
+ *
424
437
* @api
425
438
*/
426
439
public function getExitCode ()
427
440
{
441
+ if ($ this ->isSigchildEnabled () && !$ this ->enhanceSigchildCompatibility ) {
442
+ throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method ' );
443
+ }
444
+
428
445
$ this ->updateStatus ();
429
446
430
447
return $ this ->exitcode ;
@@ -438,28 +455,30 @@ public function getExitCode()
438
455
*
439
456
* @return string A string representation for the exit status code
440
457
*
458
+ * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
459
+ *
441
460
* @see http://tldp.org/LDP/abs/html/exitcodes.html
442
461
* @see http://en.wikipedia.org/wiki/Unix_signal
443
462
*/
444
463
public function getExitCodeText ()
445
464
{
446
- $ this ->updateStatus ();
465
+ $ exitcode = $ this ->getExitCode ();
447
466
448
- return isset (self ::$ exitCodes [$ this -> exitcode ]) ? self ::$ exitCodes [$ this -> exitcode ] : 'Unknown error ' ;
467
+ return isset (self ::$ exitCodes [$ exitcode ]) ? self ::$ exitCodes [$ exitcode ] : 'Unknown error ' ;
449
468
}
450
469
451
470
/**
452
471
* Checks if the process ended successfully.
453
472
*
454
473
* @return Boolean true if the process ended successfully, false otherwise
455
474
*
475
+ * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
476
+ *
456
477
* @api
457
478
*/
458
479
public function isSuccessful ()
459
480
{
460
- $ this ->updateStatus ();
461
-
462
- return 0 == $ this ->exitcode ;
481
+ return 0 == $ this ->getExitCode ();
463
482
}
464
483
465
484
/**
@@ -469,10 +488,16 @@ public function isSuccessful()
469
488
*
470
489
* @return Boolean
471
490
*
491
+ * @throws RuntimeException In case --enable-sigchild is activated
492
+ *
472
493
* @api
473
494
*/
474
495
public function hasBeenSignaled ()
475
496
{
497
+ if ($ this ->isSigchildEnabled ()) {
498
+ throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved ' );
499
+ }
500
+
476
501
$ this ->updateStatus ();
477
502
478
503
return $ this ->processInformation ['signaled ' ];
@@ -485,10 +510,16 @@ public function hasBeenSignaled()
485
510
*
486
511
* @return integer
487
512
*
513
+ * @throws RuntimeException In case --enable-sigchild is activated
514
+ *
488
515
* @api
489
516
*/
490
517
public function getTermSignal ()
491
518
{
519
+ if ($ this ->isSigchildEnabled ()) {
520
+ throw new RuntimeException ('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved ' );
521
+ }
522
+
492
523
$ this ->updateStatus ();
493
524
494
525
return $ this ->processInformation ['termsig ' ];
@@ -681,6 +712,30 @@ public function setEnhanceWindowsCompatibility($enhance)
681
712
$ this ->enhanceWindowsCompatibility = (Boolean ) $ enhance ;
682
713
}
683
714
715
+ /**
716
+ * Return whether sigchild compatibility mode is activated or not
717
+ *
718
+ * @return Boolean
719
+ */
720
+ public function getEnhanceSigchildCompatibility ()
721
+ {
722
+ return $ this ->enhanceSigchildCompatibility ;
723
+ }
724
+
725
+ /**
726
+ * Activate sigchild compatibility mode
727
+ *
728
+ * Sigchild compatibility mode is required to get the exit code and
729
+ * determine the success of a process when PHP has been compiled with
730
+ * the --enable-sigchild option
731
+ *
732
+ * @param Boolean $enhance
733
+ */
734
+ public function setEnhanceSigchildCompatibility ($ enhance )
735
+ {
736
+ $ this ->enhanceSigchildCompatibility = (Boolean ) $ enhance ;
737
+ }
738
+
684
739
/**
685
740
* Builds up the callback used by wait().
686
741
*
@@ -746,6 +801,23 @@ protected function updateOutput()
746
801
}
747
802
}
748
803
804
+ /**
805
+ * Return whether PHP has been compiled with the '--enable-sigchild' option or not
806
+ *
807
+ * @return Boolean
808
+ */
809
+ protected function isSigchildEnabled ()
810
+ {
811
+ if (null !== self ::$ sigchild ) {
812
+ return self ::$ sigchild ;
813
+ }
814
+
815
+ ob_start ();
816
+ phpinfo (INFO_GENERAL );
817
+
818
+ return self ::$ sigchild = false !== strpos (ob_get_clean (), '--enable-sigchild ' );
819
+ }
820
+
749
821
/**
750
822
* Handles the windows file handles fallbacks
751
823
*
0 commit comments