11
11
12
12
namespace Symfony \Component \Console ;
13
13
14
+ use Symfony \Component \Console \Command \AlarmableCommandInterface ;
14
15
use Symfony \Component \Console \Command \Command ;
15
16
use Symfony \Component \Console \Command \CompleteCommand ;
16
17
use Symfony \Component \Console \Command \DumpCompletionCommand ;
22
23
use Symfony \Component \Console \Completion \CompletionInput ;
23
24
use Symfony \Component \Console \Completion \CompletionSuggestions ;
24
25
use Symfony \Component \Console \Completion \Suggestion ;
26
+ use Symfony \Component \Console \Event \ConsoleAlarmEvent ;
25
27
use Symfony \Component \Console \Event \ConsoleCommandEvent ;
26
28
use Symfony \Component \Console \Event \ConsoleErrorEvent ;
27
29
use Symfony \Component \Console \Event \ConsoleSignalEvent ;
@@ -97,7 +99,7 @@ public function __construct(
97
99
$ this ->defaultCommand = 'list ' ;
98
100
if (\defined ('SIGINT ' ) && SignalRegistry::isSupported ()) {
99
101
$ this ->signalRegistry = new SignalRegistry ();
100
- $ this ->signalsToDispatchEvent = [\SIGINT , \SIGTERM , \SIGUSR1 , \SIGUSR2 ];
102
+ $ this ->signalsToDispatchEvent = [\SIGINT , \SIGTERM , \SIGUSR1 , \SIGUSR2 , \ SIGALRM ];
101
103
}
102
104
}
103
105
@@ -975,7 +977,18 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
975
977
}
976
978
}
977
979
980
+ // bind before getAlarmTime() and the console.command event, so the method and listeners have access to input options/arguments
981
+ try {
982
+ $ command ->mergeApplicationDefinition ();
983
+ $ input ->bind ($ command ->getDefinition ());
984
+ } catch (ExceptionInterface ) {
985
+ // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
986
+ }
987
+
978
988
$ commandSignals = $ command instanceof SignalableCommandInterface ? $ command ->getSubscribedSignals () : [];
989
+ if ($ command instanceof AlarmableCommandInterface && \defined ('SIGALRM ' ) && SignalRegistry::isSupported () && !\in_array (\SIGALRM , $ commandSignals , true )) {
990
+ $ commandSignals [] = \SIGALRM ;
991
+ }
979
992
if ($ commandSignals || $ this ->dispatcher && $ this ->signalsToDispatchEvent ) {
980
993
if (!$ this ->signalRegistry ) {
981
994
throw new RuntimeException ('Unable to subscribe to signal events. Make sure that the "pcntl" extension is installed and that "pcntl_*" functions are not disabled by your php.ini \'s "disable_functions" directive. ' );
@@ -992,19 +1005,34 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
992
1005
if ($ this ->dispatcher ) {
993
1006
// We register application signals, so that we can dispatch the event
994
1007
foreach ($ this ->signalsToDispatchEvent as $ signal ) {
995
- $ event = new ConsoleSignalEvent ($ command , $ input , $ output , $ signal );
996
-
997
- $ this ->signalRegistry ->register ($ signal , function ($ signal ) use ($ event , $ command , $ commandSignals ) {
998
- $ this ->dispatcher ->dispatch ($ event , ConsoleEvents::SIGNAL );
999
- $ exitCode = $ event ->getExitCode ();
1008
+ $ signalEvent = new ConsoleSignalEvent ($ command , $ input , $ output , $ signal );
1009
+ $ alarmEvent = \SIGALRM === $ signal ? new ConsoleAlarmEvent ($ command , $ input , $ output ) : null ;
1010
+
1011
+ $ this ->signalRegistry ->register ($ signal , function ($ signal ) use ($ signalEvent , $ alarmEvent , $ command , $ commandSignals , $ input , $ output ) {
1012
+ $ this ->dispatcher ->dispatch ($ signalEvent , ConsoleEvents::SIGNAL );
1013
+ $ exitCode = $ signalEvent ->getExitCode ();
1014
+
1015
+ if (null !== $ alarmEvent ) {
1016
+ if (false !== $ exitCode ) {
1017
+ $ alarmEvent ->setExitCode ($ exitCode );
1018
+ } else {
1019
+ $ alarmEvent ->abortExit ();
1020
+ }
1021
+ $ this ->dispatcher ->dispatch ($ alarmEvent , ConsoleEvents::ALARM );
1022
+ $ exitCode = $ alarmEvent ->getExitCode ();
1023
+ }
1000
1024
1025
+ if (\SIGALRM === $ signal && $ command instanceof AlarmableCommandInterface) {
1026
+ $ exitCode = $ command ->handleAlarm ($ exitCode );
1027
+ $ this ->signalRegistry ->scheduleAlarm ($ command ->getAlarmTime ($ input ));
1028
+ }
1001
1029
// If the command is signalable, we call the handleSignal() method
1002
- if (\in_array ($ signal , $ commandSignals , true )) {
1030
+ elseif (\in_array ($ signal , $ commandSignals , true )) {
1003
1031
$ exitCode = $ command ->handleSignal ($ signal , $ exitCode );
1004
1032
}
1005
1033
1006
1034
if (false !== $ exitCode ) {
1007
- $ event = new ConsoleTerminateEvent ($ command , $ event -> getInput () , $ event -> getOutput () , $ exitCode , $ signal );
1035
+ $ event = new ConsoleTerminateEvent ($ command , $ input , $ output , $ exitCode , $ signal );
1008
1036
$ this ->dispatcher ->dispatch ($ event , ConsoleEvents::TERMINATE );
1009
1037
1010
1038
exit ($ event ->getExitCode ());
@@ -1017,26 +1045,29 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
1017
1045
}
1018
1046
1019
1047
foreach ($ commandSignals as $ signal ) {
1020
- $ this ->signalRegistry ->register ($ signal , function (int $ signal ) use ($ command ): void {
1021
- if (false !== $ exitCode = $ command ->handleSignal ($ signal )) {
1048
+ $ this ->signalRegistry ->register ($ signal , function (int $ signal ) use ($ command , $ input ): void {
1049
+ if (\SIGALRM === $ signal && $ command instanceof AlarmableCommandInterface) {
1050
+ $ exitCode = $ command ->handleAlarm ();
1051
+ $ this ->signalRegistry ->scheduleAlarm ($ command ->getAlarmTime ($ input ));
1052
+ } else {
1053
+ $ exitCode = $ command ->handleSignal ($ signal );
1054
+ }
1055
+
1056
+ if (false !== $ exitCode ) {
1022
1057
exit ($ exitCode );
1023
1058
}
1024
1059
});
1025
1060
}
1061
+
1062
+ if ($ command instanceof AlarmableCommandInterface) {
1063
+ $ this ->signalRegistry ->scheduleAlarm ($ command ->getAlarmTime ($ input ));
1064
+ }
1026
1065
}
1027
1066
1028
1067
if (null === $ this ->dispatcher ) {
1029
1068
return $ command ->run ($ input , $ output );
1030
1069
}
1031
1070
1032
- // bind before the console.command event, so the listeners have access to input options/arguments
1033
- try {
1034
- $ command ->mergeApplicationDefinition ();
1035
- $ input ->bind ($ command ->getDefinition ());
1036
- } catch (ExceptionInterface ) {
1037
- // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
1038
- }
1039
-
1040
1071
$ event = new ConsoleCommandEvent ($ command , $ input , $ output );
1041
1072
$ e = null ;
1042
1073
0 commit comments