Skip to content

[Process] Introducing a new PhpSubprocess handler #48485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 3, 2023

Conversation

Toflar
Copy link
Contributor

@Toflar Toflar commented Dec 5, 2022

Q A
Branch? 6.4
Bug fix? no
New feature? yes
Deprecations? no
Tickets
License MIT
Doc PR will provide as soon as the API is clear

This PR provides a new PhpSubprocess handler which can be used to run PHP commands and taking over their parent PHP configuration. This is not super easy in PHP because the only way to do that requires a temporary ini file.
That's why I see perfect fit for it in the symfony/process component as it solves a common issue.

The code is heavily inspired/copied from composer/xdebug-handler where the requirement is similar - being able to have a child process/subprocess that takes over the config of the parent process. Hence, mentioning @Seldaek here.

Basically, this can be very useful in Symfony when you want to run bin/console other-command from within Symfony.
Let's imagine a general cronjob command that is supposed to delegate to other commands like this (simplified a lot):

#[AsCommand(name: 'run-cronjobs')]
class RunCronJobsCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $cron1 = new Process(['bin/console', 'cache:pool:prune']);
        $cron2 = new Process(['bin/console', 'something:else']);
        // etc.
    }
}

Now if you run the cronjob command itself with dynamic configuration like so: php -d memory_limit=256M bin/console run-cronjobs, the subprocesses (cache:pool:prune etc.) will not be limited to 256M because they themselves will start a completely new PHP process which will take the default PHP settings again.
This affects everything, not just memory_limit but also runtime, extensions etc. You name it.

Oftentimes, however, that's not what you want. You'd like to have the children have the same restrictions as your parent process.

With this new handler, all you have to do is to use PhpSubprocess instead of Process and it will create a temporary ini file taking over all the settings of the parent process. Done 😊

The current design is pretty straightforward without any extension points just yet (no way to fetch the ini files separately etc.). Also, it could maybe do with some more tests for the ini parsing but at this stage I would like to ask if this would even be a welcomed addition to Symfony or not 😊

@carsonbot carsonbot changed the title Introducing a new PhpSubprocess handler [Process] Introducing a new PhpSubprocess handler Dec 5, 2022
@OskarStark OskarStark changed the title [Process] Introducing a new PhpSubprocess handler [Process] Introducing a new PhpSubprocess handler Dec 5, 2022
@Seldaek
Copy link
Member

Seldaek commented Dec 5, 2022

Pinging @johnstevenson as he authored most of the xdebug-handler code. Feel free to ignore if not interested though :)

@OskarStark
Copy link
Contributor

For the record:

Fabien documented how to write CHANGELOG.md files here: symfony/symfony-docs#14830

@johnstevenson
Copy link
Contributor

I guess this will work as well as composer/xdebug-handler does (which seems to be pretty well) with its limitation of not being able to detect extensions loaded on the command line.

Proper attribution for the writeTmpIni and mergeLoadedConfig methods would be useful, in my opinion.

@Toflar
Copy link
Contributor Author

Toflar commented Dec 6, 2022

Proper attribution for the writeTmpIni and mergeLoadedConfig methods would be useful, in my opinion.

Sure, would you mind adding a code review/suggestion as to how you'd like to have this being done? Might also just add yourself as an @author?

@nicolas-grekas nicolas-grekas modified the milestones: 6.3, 6.4 May 23, 2023
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

I think this can be useful. Here are some comments.

Copy link
Contributor Author

@Toflar Toflar left a comment

Choose a reason for hiding this comment

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

@nicolas-grekas everything addressed :)

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

some minor things and good to me

Copy link
Member

@fabpot fabpot left a comment

Choose a reason for hiding this comment

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

LGTM but @Toflar, you need to rebase to remove the merge commit.

@Toflar Toflar force-pushed the feature/php-subprocess branch 3 times, most recently from b89710f to 9364391 Compare August 3, 2023 07:36
@Toflar Toflar force-pushed the feature/php-subprocess branch from 9364391 to f682a29 Compare August 3, 2023 07:38
@Toflar
Copy link
Contributor Author

Toflar commented Aug 3, 2023

Rebased and addressed the remaining reviews.

@nicolas-grekas
Copy link
Member

Thank you @Toflar.

@nicolas-grekas nicolas-grekas merged commit 0ba946a into symfony:6.4 Aug 3, 2023
@Toflar Toflar deleted the feature/php-subprocess branch August 3, 2023 09:16
@xabbuh
Copy link
Member

xabbuh commented Aug 6, 2023

Do we really need this new class? The failing tests suggest otherwise.

@nicolas-grekas
Copy link
Member

We want this feature yes. The tests are with sigchild enabled. Something to investigate. Same for the open_basedir-related failures.

This was referenced Oct 21, 2023
nicolas-grekas added a commit that referenced this pull request Nov 6, 2023
…cutable (GromNaN)

This PR was merged into the 6.4 branch.

Discussion
----------

[Process] Fix OutputMemoryLimitProcess.php cannot be executable

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

PHP files cannot be executable without shebang.

File introduced by #48485

Note that there is no other executable .php file.

Commits
-------

09992b7 PHP files cannot be executable without shebang
leofeyer pushed a commit to contao/contao that referenced this pull request Nov 12, 2023
Description
-----------

Unfortunately, our `ProcessUtil` service currently cannot be used with custom flags such as `-d memory_limit=-1`.

You currently have to do something like this:

```php
$process = $this->processUtil->createSymfonyConsoleProcess('...');

$reflection = new \ReflectionClass($process);
$commandline = $reflection->getProperty('commandline');
$commandline = $commandline->getValue($process);
array_splice($commandline, 1, 0, ['-d', 'memory_limit=-1']);
$process = new Process($commandline);

return $this->processUtil->createPromise($process);
```

First, I thought we could add a new `createSymfonyConsoleProcessWithAdditonalDirectives()` but then, as soon as you want to use something else than `new Process()` (e.g. my new [`new PhpSubprocess()`](symfony/symfony#48485)) then this wouldn't work either.

So I thought it would be best to expose the console path and binary path as getters.

Commits
-------

7e3ba37 Allow to re-use the ProcessUtil data
leofeyer pushed a commit to contao/core-bundle that referenced this pull request Nov 12, 2023
Description
-----------

Unfortunately, our `ProcessUtil` service currently cannot be used with custom flags such as `-d memory_limit=-1`.

You currently have to do something like this:

```php
$process = $this->processUtil->createSymfonyConsoleProcess('...');

$reflection = new \ReflectionClass($process);
$commandline = $reflection->getProperty('commandline');
$commandline = $commandline->getValue($process);
array_splice($commandline, 1, 0, ['-d', 'memory_limit=-1']);
$process = new Process($commandline);

return $this->processUtil->createPromise($process);
```

First, I thought we could add a new `createSymfonyConsoleProcessWithAdditonalDirectives()` but then, as soon as you want to use something else than `new Process()` (e.g. my new [`new PhpSubprocess()`](symfony/symfony#48485)) then this wouldn't work either.

So I thought it would be best to expose the console path and binary path as getters.

Commits
-------

7e3ba373 Allow to re-use the ProcessUtil data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants