Skip to content

Commit 532f99e

Browse files
Merge branch '6.0' into 6.1
* 6.0: (23 commits) cs fix [Messenger] Fix Doctrine transport on MySQL [Filesystem] Remove needless `mb_*` calls [Translator] Fix translator overlapse [Yaml] Improve test coverage in DumperTest and ParserTest Extract dispatching console signal handling and include subscribers [Mailer] Fix error message in case of an STMP error [HttpClient] Fix shared connections not being freed on PHP < 8 [HttpFoundation] Fix invalid ID not regenerated with native PHP file sessions [HttpClient] Fix memory leak when using StreamWrapper minor: fix test [Serializer] Fix error message remove the ChatterInterface alias when the chatter service is removed Bump Symfony version to 6.0.12 Update VERSION for 6.0.11 Update CHANGELOG for 6.0.11 Bump Symfony version to 5.4.12 Update VERSION for 5.4.11 Update CHANGELOG for 5.4.11 Bump Symfony version to 4.4.45 ...
2 parents 43fcb5c + bfbf0e8 commit 532f99e

File tree

2 files changed

+157
-38
lines changed

2 files changed

+157
-38
lines changed

Application.php

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -957,22 +957,31 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
957957
}
958958
}
959959

960-
if ($command instanceof SignalableCommandInterface && ($this->signalsToDispatchEvent || $command->getSubscribedSignals())) {
961-
if (!$this->signalRegistry) {
962-
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.');
963-
}
960+
if ($this->signalsToDispatchEvent) {
961+
$commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : [];
962+
$dispatchSignals = $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::SIGNAL);
964963

965-
if (Terminal::hasSttyAvailable()) {
966-
$sttyMode = shell_exec('stty -g');
964+
if ($commandSignals || $dispatchSignals) {
965+
if (!$this->signalRegistry) {
966+
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.');
967+
}
967968

968-
foreach ([\SIGINT, \SIGTERM] as $signal) {
969-
$this->signalRegistry->register($signal, static function () use ($sttyMode) {
970-
shell_exec('stty '.$sttyMode);
971-
});
969+
if (Terminal::hasSttyAvailable()) {
970+
$sttyMode = shell_exec('stty -g');
971+
972+
foreach ([\SIGINT, \SIGTERM] as $signal) {
973+
$this->signalRegistry->register($signal, static function () use ($sttyMode) {
974+
shell_exec('stty '.$sttyMode);
975+
});
976+
}
977+
}
978+
979+
foreach ($commandSignals as $signal) {
980+
$this->signalRegistry->register($signal, [$command, 'handleSignal']);
972981
}
973982
}
974983

975-
if ($this->dispatcher) {
984+
if ($dispatchSignals) {
976985
foreach ($this->signalsToDispatchEvent as $signal) {
977986
$event = new ConsoleSignalEvent($command, $input, $output, $signal);
978987

@@ -988,10 +997,6 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
988997
});
989998
}
990999
}
991-
992-
foreach ($command->getSubscribedSignals() as $signal) {
993-
$this->signalRegistry->register($signal, [$command, 'handleSignal']);
994-
}
9951000
}
9961001

9971002
if (null === $this->dispatcher) {

Tests/ApplicationTest.php

Lines changed: 137 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
2323
use Symfony\Component\Console\Event\ConsoleCommandEvent;
2424
use Symfony\Component\Console\Event\ConsoleErrorEvent;
25+
use Symfony\Component\Console\Event\ConsoleSignalEvent;
2526
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
2627
use Symfony\Component\Console\Exception\CommandNotFoundException;
2728
use Symfony\Component\Console\Exception\NamespaceNotFoundException;
@@ -43,6 +44,8 @@
4344
use Symfony\Component\Console\Tester\ApplicationTester;
4445
use Symfony\Component\DependencyInjection\ContainerBuilder;
4546
use Symfony\Component\EventDispatcher\EventDispatcher;
47+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
48+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
4649
use Symfony\Component\Process\Process;
4750

4851
class ApplicationTest extends TestCase
@@ -1862,39 +1865,107 @@ public function testCommandNameMismatchWithCommandLoaderKeyThrows()
18621865
/**
18631866
* @requires extension pcntl
18641867
*/
1865-
public function testSignal()
1868+
public function testSignalListenerNotCalledByDefault()
18661869
{
1867-
$command = new SignableCommand();
1870+
$command = new SignableCommand(false);
18681871

18691872
$dispatcherCalled = false;
18701873
$dispatcher = new EventDispatcher();
18711874
$dispatcher->addListener('console.signal', function () use (&$dispatcherCalled) {
18721875
$dispatcherCalled = true;
18731876
});
18741877

1875-
$application = new Application();
1876-
$application->setAutoExit(false);
1877-
$application->setDispatcher($dispatcher);
1878-
$application->setSignalsToDispatchEvent(\SIGALRM);
1879-
$application->add(new LazyCommand('signal', [], '', false, function () use ($command) { return $command; }, true));
1880-
1881-
$this->assertFalse($command->signaled);
1882-
$this->assertFalse($dispatcherCalled);
1878+
$application = $this->createSignalableApplication($command, $dispatcher);
18831879

18841880
$this->assertSame(0, $application->run(new ArrayInput(['signal'])));
18851881
$this->assertFalse($command->signaled);
18861882
$this->assertFalse($dispatcherCalled);
1883+
}
1884+
1885+
/**
1886+
* @requires extension pcntl
1887+
*/
1888+
public function testSignalListener()
1889+
{
1890+
$command = new SignableCommand();
1891+
1892+
$dispatcherCalled = false;
1893+
$dispatcher = new EventDispatcher();
1894+
$dispatcher->addListener('console.signal', function () use (&$dispatcherCalled) {
1895+
$dispatcherCalled = true;
1896+
});
1897+
1898+
$application = $this->createSignalableApplication($command, $dispatcher);
18871899

1888-
$command->loop = 100000;
1889-
pcntl_alarm(1);
18901900
$this->assertSame(1, $application->run(new ArrayInput(['signal'])));
1891-
$this->assertTrue($command->signaled);
18921901
$this->assertTrue($dispatcherCalled);
1902+
$this->assertTrue($command->signaled);
1903+
}
1904+
1905+
/**
1906+
* @requires extension pcntl
1907+
*/
1908+
public function testSignalSubscriberNotCalledByDefault()
1909+
{
1910+
$command = new BaseSignableCommand(false);
1911+
1912+
$subscriber = new SignalEventSubscriber();
1913+
$dispatcher = new EventDispatcher();
1914+
$dispatcher->addSubscriber($subscriber);
1915+
1916+
$application = $this->createSignalableApplication($command, $dispatcher);
1917+
1918+
$this->assertSame(0, $application->run(new ArrayInput(['signal'])));
1919+
$this->assertFalse($subscriber->signaled);
1920+
}
1921+
1922+
/**
1923+
* @requires extension pcntl
1924+
*/
1925+
public function testSignalSubscriber()
1926+
{
1927+
$command = new BaseSignableCommand();
1928+
1929+
$subscriber1 = new SignalEventSubscriber();
1930+
$subscriber2 = new SignalEventSubscriber();
1931+
1932+
$dispatcher = new EventDispatcher();
1933+
$dispatcher->addSubscriber($subscriber1);
1934+
$dispatcher->addSubscriber($subscriber2);
1935+
1936+
$application = $this->createSignalableApplication($command, $dispatcher);
1937+
1938+
$this->assertSame(1, $application->run(new ArrayInput(['signal'])));
1939+
$this->assertTrue($subscriber1->signaled);
1940+
$this->assertTrue($subscriber2->signaled);
1941+
}
1942+
1943+
/**
1944+
* @requires extension pcntl
1945+
*/
1946+
public function testSetSignalsToDispatchEvent()
1947+
{
1948+
$command = new BaseSignableCommand();
1949+
1950+
$subscriber = new SignalEventSubscriber();
1951+
1952+
$dispatcher = new EventDispatcher();
1953+
$dispatcher->addSubscriber($subscriber);
1954+
1955+
$application = $this->createSignalableApplication($command, $dispatcher);
1956+
$application->setSignalsToDispatchEvent(\SIGUSR2);
1957+
$this->assertSame(0, $application->run(new ArrayInput(['signal'])));
1958+
$this->assertFalse($subscriber->signaled);
1959+
1960+
$application = $this->createSignalableApplication($command, $dispatcher);
1961+
$application->setSignalsToDispatchEvent(\SIGUSR1);
1962+
$this->assertSame(1, $application->run(new ArrayInput(['signal'])));
1963+
$this->assertTrue($subscriber->signaled);
18931964
}
18941965

18951966
public function testSignalableCommandInterfaceWithoutSignals()
18961967
{
1897-
$command = new SignableCommand();
1968+
$command = new SignableCommand(false);
18981969

18991970
$dispatcher = new EventDispatcher();
19001971
$application = new Application();
@@ -1936,6 +2007,18 @@ public function testSignalableRestoresStty()
19362007

19372008
$this->assertSame($previousSttyMode, $sttyMode);
19382009
}
2010+
2011+
private function createSignalableApplication(Command $command, ?EventDispatcherInterface $dispatcher): Application
2012+
{
2013+
$application = new Application();
2014+
$application->setAutoExit(false);
2015+
if ($dispatcher) {
2016+
$application->setDispatcher($dispatcher);
2017+
}
2018+
$application->add(new LazyCommand('signal', [], '', false, function () use ($command) { return $command; }, true));
2019+
2020+
return $application;
2021+
}
19392022
}
19402023

19412024
class CustomApplication extends Application
@@ -1988,23 +2071,24 @@ public function isEnabled(): bool
19882071
}
19892072

19902073
#[AsCommand(name: 'signal')]
1991-
class SignableCommand extends Command implements SignalableCommandInterface
2074+
class BaseSignableCommand extends Command
19922075
{
19932076
public $signaled = false;
1994-
public $loop = 100;
1995-
1996-
public function getSubscribedSignals(): array
1997-
{
1998-
return SignalRegistry::isSupported() ? [\SIGALRM] : [];
1999-
}
2077+
public $loop = 1000;
2078+
private $emitsSignal;
20002079

2001-
public function handleSignal(int $signal): void
2080+
public function __construct(bool $emitsSignal = true)
20022081
{
2003-
$this->signaled = true;
2082+
parent::__construct();
2083+
$this->emitsSignal = $emitsSignal;
20042084
}
20052085

20062086
protected function execute(InputInterface $input, OutputInterface $output): int
20072087
{
2088+
if ($this->emitsSignal) {
2089+
posix_kill(posix_getpid(), SIGUSR1);
2090+
}
2091+
20082092
for ($i = 0; $i < $this->loop; ++$i) {
20092093
usleep(100);
20102094
if ($this->signaled) {
@@ -2015,3 +2099,33 @@ protected function execute(InputInterface $input, OutputInterface $output): int
20152099
return 0;
20162100
}
20172101
}
2102+
2103+
#[AsCommand(name: 'signal')]
2104+
class SignableCommand extends BaseSignableCommand implements SignalableCommandInterface
2105+
{
2106+
public function getSubscribedSignals(): array
2107+
{
2108+
return SignalRegistry::isSupported() ? [\SIGUSR1] : [];
2109+
}
2110+
2111+
public function handleSignal(int $signal): void
2112+
{
2113+
$this->signaled = true;
2114+
}
2115+
}
2116+
2117+
class SignalEventSubscriber implements EventSubscriberInterface
2118+
{
2119+
public $signaled = false;
2120+
2121+
public function onSignal(ConsoleSignalEvent $event): void
2122+
{
2123+
$this->signaled = true;
2124+
$event->getCommand()->signaled = true;
2125+
}
2126+
2127+
public static function getSubscribedEvents(): array
2128+
{
2129+
return ['console.signal' => 'onSignal'];
2130+
}
2131+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy