1414use Symfony \Component \Console \Command \Command ;
1515use Symfony \Component \Console \Command \HelpCommand ;
1616use Symfony \Component \Console \Command \ListCommand ;
17+ use Symfony \Component \Console \Command \SignalableCommandInterface ;
1718use Symfony \Component \Console \CommandLoader \CommandLoaderInterface ;
1819use Symfony \Component \Console \Event \ConsoleCommandEvent ;
1920use Symfony \Component \Console \Event \ConsoleErrorEvent ;
@@ -79,13 +80,18 @@ class Application implements ResetInterface
7980 private $ singleCommand = false ;
8081 private $ initialized ;
8182 private $ signalRegistry ;
83+ private $ signalsToDispatchEvent = [];
8284
8385 public function __construct (string $ name = 'UNKNOWN ' , string $ version = 'UNKNOWN ' )
8486 {
8587 $ this ->name = $ name ;
8688 $ this ->version = $ version ;
8789 $ this ->terminal = new Terminal ();
8890 $ this ->defaultCommand = 'list ' ;
91+ $ this ->signalRegistry = new SignalRegistry ();
92+ if (\defined ('SIGINT ' )) {
93+ $ this ->signalsToDispatchEvent = [SIGINT , SIGTERM , SIGUSR1 , SIGUSR2 ];
94+ }
8995 }
9096
9197 /**
@@ -101,9 +107,14 @@ public function setCommandLoader(CommandLoaderInterface $commandLoader)
101107 $ this ->commandLoader = $ commandLoader ;
102108 }
103109
104- public function setSignalRegistry ( SignalRegistry $ signalRegistry )
110+ public function getSignalRegistry (): SignalRegistry
105111 {
106- $ this ->signalRegistry = $ signalRegistry ;
112+ return $ this ->signalRegistry ;
113+ }
114+
115+ public function setSignalsToDispatchEvent (int ...$ signalsToDispatchEvent )
116+ {
117+ $ this ->signalsToDispatchEvent = $ signalsToDispatchEvent ;
107118 }
108119
109120 /**
@@ -268,14 +279,20 @@ public function doRun(InputInterface $input, OutputInterface $output)
268279 $ command = $ this ->find ($ alternative );
269280 }
270281
271- if ($ this ->signalRegistry ) {
272- foreach ($ this ->signalRegistry ->getHandlingSignals () as $ handlingSignal ) {
273- $ event = new ConsoleSignalEvent ($ command , $ input , $ output , $ handlingSignal );
274- $ onSignalHandler = function () use ($ event ) {
282+ if ($ this ->dispatcher ) {
283+ foreach ($ this ->signalsToDispatchEvent as $ signal ) {
284+ $ event = new ConsoleSignalEvent ($ command , $ input , $ output , $ signal );
285+
286+ $ this ->signalRegistry ->register ($ signal , function ($ signal , $ hasNext ) use ($ event ) {
275287 $ this ->dispatcher ->dispatch ($ event , ConsoleEvents::SIGNAL );
276- };
277288
278- $ this ->signalRegistry ->register ($ handlingSignal , $ onSignalHandler );
289+ // No more handlers, we try to simulate PHP default behavior
290+ if (!$ hasNext ) {
291+ if (!\in_array ($ signal , [SIGUSR1 , SIGUSR2 ], true )) {
292+ exit (0 );
293+ }
294+ }
295+ });
279296 }
280297 }
281298
@@ -926,6 +943,12 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
926943 }
927944 }
928945
946+ if ($ command instanceof SignalableCommandInterface) {
947+ foreach ($ command ->getSubscribedSignals () as $ signal ) {
948+ $ this ->signalRegistry ->register ($ signal , [$ command , 'handleSignal ' ]);
949+ }
950+ }
951+
929952 if (null === $ this ->dispatcher ) {
930953 return $ command ->run ($ input , $ output );
931954 }
0 commit comments