Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 97e4391

Browse filesBrowse files
HypeMCfabpot
authored andcommitted
[Console] Add ability to schedule alarm signals and a console.alarm event
1 parent 83beaba commit 97e4391
Copy full SHA for 97e4391

File tree

Expand file treeCollapse file tree

7 files changed

+382
-14
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+382
-14
lines changed

‎src/Symfony/Component/Console/Application.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/Application.php
+47-12Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Console\Completion\CompletionInput;
2323
use Symfony\Component\Console\Completion\CompletionSuggestions;
2424
use Symfony\Component\Console\Completion\Suggestion;
25+
use Symfony\Component\Console\Event\ConsoleAlarmEvent;
2526
use Symfony\Component\Console\Event\ConsoleCommandEvent;
2627
use Symfony\Component\Console\Event\ConsoleErrorEvent;
2728
use Symfony\Component\Console\Event\ConsoleSignalEvent;
@@ -88,6 +89,7 @@ class Application implements ResetInterface
8889
private bool $initialized = false;
8990
private ?SignalRegistry $signalRegistry = null;
9091
private array $signalsToDispatchEvent = [];
92+
private ?int $alarmInterval = null;
9193

9294
public function __construct(
9395
private string $name = 'UNKNOWN',
@@ -97,7 +99,7 @@ public function __construct(
9799
$this->defaultCommand = 'list';
98100
if (\defined('SIGINT') && SignalRegistry::isSupported()) {
99101
$this->signalRegistry = new SignalRegistry();
100-
$this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2];
102+
$this->signalsToDispatchEvent = [\SIGINT, \SIGQUIT, \SIGTERM, \SIGUSR1, \SIGUSR2, \SIGALRM];
101103
}
102104
}
103105

@@ -128,6 +130,22 @@ public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent): void
128130
$this->signalsToDispatchEvent = $signalsToDispatchEvent;
129131
}
130132

133+
/**
134+
* Sets the interval to schedule a SIGALRM signal in seconds.
135+
*/
136+
public function setAlarmInterval(?int $seconds): void
137+
{
138+
$this->alarmInterval = $seconds;
139+
$this->scheduleAlarm();
140+
}
141+
142+
private function scheduleAlarm(): void
143+
{
144+
if (null !== $this->alarmInterval) {
145+
$this->getSignalRegistry()->scheduleAlarm($this->alarmInterval);
146+
}
147+
}
148+
131149
/**
132150
* Runs the current application.
133151
*
@@ -981,34 +999,47 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
981999

9821000
$commandSignals = $command instanceof SignalableCommandInterface ? $command->getSubscribedSignals() : [];
9831001
if ($commandSignals || $this->dispatcher && $this->signalsToDispatchEvent) {
984-
if (!$this->signalRegistry) {
985-
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.');
986-
}
1002+
$signalRegistry = $this->getSignalRegistry();
9871003

9881004
if (Terminal::hasSttyAvailable()) {
9891005
$sttyMode = shell_exec('stty -g');
9901006

9911007
foreach ([\SIGINT, \SIGQUIT, \SIGTERM] as $signal) {
992-
$this->signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode));
1008+
$signalRegistry->register($signal, static fn () => shell_exec('stty '.$sttyMode));
9931009
}
9941010
}
9951011

9961012
if ($this->dispatcher) {
9971013
// We register application signals, so that we can dispatch the event
9981014
foreach ($this->signalsToDispatchEvent as $signal) {
999-
$event = new ConsoleSignalEvent($command, $input, $output, $signal);
1000-
1001-
$this->signalRegistry->register($signal, function ($signal) use ($event, $command, $commandSignals) {
1002-
$this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
1003-
$exitCode = $event->getExitCode();
1015+
$signalEvent = new ConsoleSignalEvent($command, $input, $output, $signal);
1016+
$alarmEvent = \SIGALRM === $signal ? new ConsoleAlarmEvent($command, $input, $output) : null;
1017+
1018+
$signalRegistry->register($signal, function ($signal) use ($signalEvent, $alarmEvent, $command, $commandSignals, $input, $output) {
1019+
$this->dispatcher->dispatch($signalEvent, ConsoleEvents::SIGNAL);
1020+
$exitCode = $signalEvent->getExitCode();
1021+
1022+
if (null !== $alarmEvent) {
1023+
if (false !== $exitCode) {
1024+
$alarmEvent->setExitCode($exitCode);
1025+
} else {
1026+
$alarmEvent->abortExit();
1027+
}
1028+
$this->dispatcher->dispatch($alarmEvent);
1029+
$exitCode = $alarmEvent->getExitCode();
1030+
}
10041031

10051032
// If the command is signalable, we call the handleSignal() method
10061033
if (\in_array($signal, $commandSignals, true)) {
10071034
$exitCode = $command->handleSignal($signal, $exitCode);
10081035
}
10091036

1037+
if (\SIGALRM === $signal) {
1038+
$this->scheduleAlarm();
1039+
}
1040+
10101041
if (false !== $exitCode) {
1011-
$event = new ConsoleTerminateEvent($command, $event->getInput(), $event->getOutput(), $exitCode, $signal);
1042+
$event = new ConsoleTerminateEvent($command, $input, $output, $exitCode, $signal);
10121043
$this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
10131044

10141045
exit($event->getExitCode());
@@ -1021,7 +1052,11 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI
10211052
}
10221053

10231054
foreach ($commandSignals as $signal) {
1024-
$this->signalRegistry->register($signal, function (int $signal) use ($command): void {
1055+
$signalRegistry->register($signal, function (int $signal) use ($command): void {
1056+
if (\SIGALRM === $signal) {
1057+
$this->scheduleAlarm();
1058+
}
1059+
10251060
if (false !== $exitCode = $command->handleSignal($signal)) {
10261061
exit($exitCode);
10271062
}

‎src/Symfony/Component/Console/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* [BC BREAK] Add silent verbosity (`--silent`/`SHELL_VERBOSITY=-2`) to suppress all output, including errors
1010
* Add `OutputInterface::isSilent()`, `Output::isSilent()`, `OutputStyle::isSilent()` methods
1111
* Add a configurable finished indicator to the progress indicator to show that the progress is finished
12+
* Add ability to schedule alarm signals and a `ConsoleAlarmEvent`
1213

1314
7.1
1415
---
+47Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Console\Event;
13+
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
17+
18+
final class ConsoleAlarmEvent extends ConsoleEvent
19+
{
20+
public function __construct(
21+
Command $command,
22+
InputInterface $input,
23+
OutputInterface $output,
24+
private int|false $exitCode = 0,
25+
) {
26+
parent::__construct($command, $input, $output);
27+
}
28+
29+
public function setExitCode(int $exitCode): void
30+
{
31+
if ($exitCode < 0 || $exitCode > 255) {
32+
throw new \InvalidArgumentException('Exit code must be between 0 and 255.');
33+
}
34+
35+
$this->exitCode = $exitCode;
36+
}
37+
38+
public function abortExit(): void
39+
{
40+
$this->exitCode = false;
41+
}
42+
43+
public function getExitCode(): int|false
44+
{
45+
return $this->exitCode;
46+
}
47+
}

‎src/Symfony/Component/Console/SignalRegistry/SignalRegistry.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Console/SignalRegistry/SignalRegistry.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,12 @@ public function handle(int $signal): void
5454
$signalHandler($signal, $hasNext);
5555
}
5656
}
57+
58+
/**
59+
* @internal
60+
*/
61+
public function scheduleAlarm(int $seconds): void
62+
{
63+
pcntl_alarm($seconds);
64+
}
5765
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.