Skip to content

Conversation

michalsn
Copy link
Member

Description
This PR adds SignalTrait that provides unified handling of operating system signals (such as SIGINT and SIGTERM, etc.) in CLI commands. This ensures that long-running or sensitive CLI processes can gracefully handle interruptions before exiting.

In addition, this PR updates the way migration commands are handled to prevent interruptions during critical changes in the database, reducing the risk of leaving the schema in an inconsistent state.

Further details, usage examples, and guidelines are available in the updated user guide.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@michalsn michalsn added new feature PRs for new features 4.7 labels Aug 22, 2025
@neznaika0
Copy link
Contributor

Great work! I'm not sure if spark serve needs management.

@michalsn
Copy link
Member Author

I'm not sure if spark serve needs management.

I believe we're good. Besides, this is just for development purposes anyway.

Copy link
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add ext-pcntl and ext-posix to the suggest in composer.json.

Copy link
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Looks good overall!

@michalsn
Copy link
Member Author

I'm wondering if we should offer translations for some messages, such as: "PCNTL extension not available. Signal handling disabled." Or is it acceptable to leave them untranslatable, since they are general error messages?

@paulbalandan
Copy link
Member

I think yes to be consistent with the rest of the framework.

@neznaika0
Copy link
Contributor

Is it possible to ping a "translation" repository? To add new phrases

@michalsn
Copy link
Member Author

Not sure about the procedure here... @paulbalandan, are we waiting for the 4.7 release so the repo picks it up automatically, or is it the other way around?

@paulbalandan
Copy link
Member

Unfortunately, translations repo only picks up the latest strings from develop branch. These won't be picked up until 4.7 is released and merged to develop.

@michalsn
Copy link
Member Author

Okay, thanks for confirming. I don't think it's a problem if translations only become available after 4.7.

@michalsn
Copy link
Member Author

michalsn commented Sep 5, 2025

If someone has an idea why Psalm started failing, please let me know. I cannot reproduce this locally.

@neznaika0
Copy link
Contributor

neznaika0 commented Sep 5, 2025

I have error. Arch Linux

$ utils/vendor/bin/psalm

Running on PHP 8.4.12, Psalm 6.13.1@1e3b7f0a8ab32b23197b91107adc0a7ed8a05b51.

JIT acceleration: ON

JIT compilation in progress... Done.

Process plugin adjustments...
Target PHP version: 8.1 (inferred from composer.json).

Scanning files...

[Error]
Class "Tests\Support\Commands\SignalCommand" not found
at ROOTPATH/tests/_support/Commands/SignalCommandNoPcntl.php:19

@neznaika0
Copy link
Contributor

neznaika0 commented Sep 5, 2025

It looks like a bug. Check out the autoload for psalm:

foreach ($directories as $directory) {
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(
$directory,
RecursiveDirectoryIterator::UNIX_PATHS | RecursiveDirectoryIterator::CURRENT_AS_FILEINFO,
),
RecursiveIteratorIterator::CHILD_FIRST,
);

But sorting the files does not allow us to find the class because it has not loaded yet.

Scanning files...

string(84) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/Unsuffixable.php"
string(78) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/Foobar.php"
string(86) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/InvalidCommand.php"
string(67) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands"
string(79) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/AppInfo.php"
string(58) "/home/neznaika0/www/codeigniter/development/tests/_support"
string(84) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/AbstractInfo.php"
# There should be string(48) "tests/_support/Commands/SignalCommand.php"
string(92) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/SignalCommandNoPcntl.php"
string(85) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/SignalCommand.php"
string(87) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/LanguageCommand.php"
string(92) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/SignalCommandNoPosix.php"
string(84) "/home/neznaika0/www/codeigniter/development/tests/_support/Commands/ParamsReveal.php"

[Error]
Class "Tests\Support\Commands\SignalCommand" not found
at ROOTPATH/tests/_support/Commands/SignalCommandNoPcntl.php:19

It follows that there may be some errors in other code.

@michalsn try:

    // TODO: Temporary solution.
    $files = iterator_to_array($iterator, false);
    unset($iterator);
    usort($files, function(SplFileInfo $a, SplFileInfo $b) {
        return strcmp($a->getPathname(), $b->getPathname());
    });

    /** @var SplFileInfo $file */
    foreach ($files as $file) {

@michalsn
Copy link
Member Author

michalsn commented Sep 5, 2025

Thanks, @neznaika0. I've already pushed a fix. Not sure if this is the ideal long-term solution, but it works for now. Maybe @paulbalandan has a better approach?

@neznaika0
Copy link
Contributor

Yes, it's temporary. In fact, you need an autoloader as in the system: calling the class >> reading the class file.

Copy link
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know either why files are sorted differently across OS but the fix looks good at the moment.

@neznaika0
Copy link
Contributor

The problem is not sorting.
I did not check: Will the class be loaded if it is (for example) in another directory that will be scanned later?

Files:
DirA -> DirB -> class A (load first, call B inside)
DirX -> DirY -> class B (load after A)

Even if the order is correct, the class will load later

@michalsn michalsn merged commit f03ce85 into codeigniter4:4.7 Sep 5, 2025
50 checks passed
@michalsn
Copy link
Member Author

michalsn commented Sep 5, 2025

Thank you @paulbalandan and @neznaika0

@michalsn michalsn deleted the feat/signals branch September 6, 2025 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.7 new feature PRs for new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants