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