Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

[Process] Fix Inconsistent Exit Status in proc_get_status for PHP Versions Below 8.3#53821

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
nicolas-grekas merged 1 commit intosymfony:5.4fromLuc45:patch-2
Feb 9, 2024

Conversation

Luc45
Copy link
Contributor

@Luc45Luc45 commentedFeb 7, 2024
edited
Loading

QA
Branch?5.4
Bug fix?yes
New feature?no
Deprecations?no
IssuesN/A
LicenseMIT

This PR addresses a bug in Symfony's Process component affecting PHP versions prior to 8.3. In these versions, callingproc_get_status multiple times on the same process resource only returns the correct exit status on the first call, with subsequent calls returning -1 due to the process being discarded. This behavior can lead to race conditions and incorrect process status reporting in Symfony applications.

PHP 8.3changelog notes/fix PR:

Executing proc_get_status() multiple times

Executing proc_get_status() multiple times will now always return the right value on POSIX systems.
Previously, only the first call of the function returned the right value. Executing proc_close()
after proc_get_status() will now also return the right exit code. Previously this would return -1.

Symfony Process is very good at avoiding this, but it's possible to trigger this behavior if you pass the Process as a reference to the output callback itself, and inside of it you invoke a method that eventually triggersproc_get_status, such asisRunning,isSuccessful, etc.

This PR tries to mimick PHP 8.3 behavior in older versions, caching the first reported valid exit status code once the process exits, and reusing the cached value if the new exit status code is now invalid.

I believe this bug has been pestering Symfony Process for a long time, as perthis Stack Overflow question, but it was very hard to track it down, and only happens in certain conditions, and it also have a racing condition factor depending on the time between the last output of the process and it's termination.

Changes:

  • Added caching mechanism for the exit status in the Process component.
  • Ensured the cached status is used for subsequentproc_get_status calls if PHP version is below 8.3.

Proof of Concept:

To demonstrate the issue and the effectiveness of the fix, a proof of concept script is included below. This script uses Symfony's Process component to start a subprocess that outputs a message and exits with a specific status code. The script then attempts to retrieve the exit status of the process using getExitCode(). In PHP versions prior to 8.3, without the proposed fix, this script will often incorrectly report an exit code of -1 due to the race condition described earlier.

<?phpif (getenv('OUTPUT' ) ) {#echo 'This should fail when "wait" gets large';sleep(2 );echo'This should fail even when "wait" is small';die(123 );}useSymfony\Component\Process\Process;require_once__DIR__ .'/vendor/autoload.php';$wait =0;do {// Increasingly bigger waits.$wait +=100000;echosprintf('Wait: %s',$wait ) .PHP_EOL;$p =newProcess( ['php',__FILE__ ],__DIR__, ['OUTPUT' =>1,] );$p->start(function (string$type,string$out )use ($p ) {echo$out .PHP_EOL;/** * Calling most methods in Symfony Process that triggers * updateStatus() can potentially trigger the -1 bug. * * @see Process::updateStatus() */echosprintf('Is Running: %s',$p->isRunning() ?'Yes' :'No' ) .PHP_EOL;echosprintf('Exit Code: %s',$p->getExitCode() ) .PHP_EOL;} );while ($p->isRunning() ) {usleep($wait );}if ( !$p->isSuccessful() ) {break;}}while (true );$is_started =$p->isStarted();$is_running =$p->isRunning();$exit_code  =$p->getExitCode();echosprintf('Started: %s, Running: %s, Exit code: %s',$is_started,$is_running,$exit_code ) .PHP_EOL;

Impact:

  • This change only affects Symfony applications running on PHP versions below 8.3.
  • It improves the reliability of process status reporting in these environments.
  • No breaking changes or backward compatibility issues are introduced.

Testing:

I haven't added tests to this PR because:

  • This bug involves racing conditions, which is hard to replicate.
  • It's past 1 AM local time right now, and I've been debugging this for the past 6 hours.
  • The provided "Proof of Concept" can serve as an initial check to confirm the bug.

I'm really not the type of developer that does not write tests, but I beg my pardon for the reasons above.

Considerations

  • Based on theproc_open implementation, this fix might not be needed on Windows.
  • You can find additional context for this bug in thisStack Overflow answer.

@carsonbot
Copy link

Hey!

Thanks for your PR. You are targeting branch "5.4" but it seems your PR description refers to branch "5.4, 6.4, 7.0".
Could you update the PR description or change target branch? This helps core maintainers a lot.

Cheers!

Carsonbot

Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

Can you please add a test case to cover the behavior?

@carsonbotcarsonbot changed the titleFix Inconsistent Exit Status in proc_get_status for PHP Versions Below 8.3[Process] Fix Inconsistent Exit Status in proc_get_status for PHP Versions Below 8.3Feb 7, 2024
@nicolas-grekas
Copy link
Member

Reading now your full description... I'd still be great to figure out a test case :)

@stof
Copy link
Member

stof commentedFeb 7, 2024

A first testcase could be one running your reproducer (even if it does not fail 100% of the time due to relying on a race condition, it would still be likely to failsometimes if we reintroduce the issue in the future)

@Luc45
Copy link
ContributorAuthor

I've added a test that reproduces the bug, it fails on7.1 tag and passes on this branch.

@Luc45
Copy link
ContributorAuthor

If I remove the fix, you can see the racing condition factor in the tests causing the tests to fail erratically on the longRunning process test.

image

@Luc45
Copy link
ContributorAuthor

Luc45 commentedFeb 7, 2024
edited
Loading

My tests usessleep to mimick racing condition scenarios, which adds a total of 4 seconds to the Process test suite, which is not ideal. I've grouped them intime-sensitive, and I'm open to ideas. Maybe we could reduce the sleep from 2 to 1 second. [Done]

@Luc45
Copy link
ContributorAuthor

I don't know whyCliDumperTest::testCollapse is failing, as it doesn't seem to useProcess at all.

Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

LGTM thanks.

@@ -1556,7 +1602,6 @@ public function testNotTerminableInputPipe()

/**
* @param string|array $commandline
* @param mixed $input
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I didn't want to touch this but Fabbot code style tests asks to remove it. Bringing it up just for clarity.

@Luc45
Copy link
ContributorAuthor

7.2 tests fail because of the short closure syntax, want me to keep it@nicolas-grekas?

@nicolas-grekas
Copy link
Member

nope, indeed

@Luc45
Copy link
ContributorAuthor

Tests in Windows is failing because it doesn't havesleep. I've tweaked it to use inline PHP withsleep instead, and I can confirm it works by prependingtime to the command, adjusting the sleep in the spawning process and re-running the test.

  • Sleep 5:php ./phpunit symfony src/Symfony/Component/Process 83,90s user 59,06s system 688% cpu 20,776 total
  • Sleep 1:php ./phpunit symfony src/Symfony/Component/Process 80,13s user 58,70s system 1094% cpu 12,684 total

Since it runs a bunch of tests in parallel, we have to ignore 80s and 59s because that's CPU time, and look at "actual time" which is the last one: 20s and 12s respectively, which sounds about right. Re-running.

@Luc45
Copy link
ContributorAuthor

The remaining Windows failures seems unrelated

@nicolas-grekas
Copy link
Member

Thank you@Luc45.

@nicolas-grekasnicolas-grekas merged commit3870d1e intosymfony:5.4Feb 9, 2024
nicolas-grekas added a commit that referenced this pull requestFeb 12, 2024
…-daubois)This PR was merged into the 5.4 branch.Discussion----------[Process] Fix failing tests causing segfaults| Q             | A| ------------- | ---| Branch?       | 5.4| Bug fix?      | yes| New feature?  | no| Deprecations? | no| Issues        | Fix tests| License       | MIT[This PR](#53821) introduces some code that [triggers segfaults](https://github.com/symfony/symfony/actions/runs/7870905388/job/21473073396) in newer branches (7.x especially). We can achieve the same goal by using some bash script which is lighter and avoid the segfaults. I first tried this fix on 7.x and solved the issue (that does not happen on older branches).Commits-------041e178 [Process] Fix failing tests causing segfaults
This was referencedFeb 27, 2024
github-merge-queuebot pushed a commit to Lendable/composer-license-checker that referenced this pull requestMar 2, 2024
[![MendRenovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)This PR contains the following updates:| Package | Change | Age | Adoption | Passing | Confidence ||---|---|---|---|---|---|| [symfony/console](https://symfony.com)([source](https://togithub.com/symfony/console)) | `6.4.4` -> `7.0.4` |[![age](https://developer.mend.io/api/mc/badges/age/packagist/symfony%2fconsole/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![adoption](https://developer.mend.io/api/mc/badges/adoption/packagist/symfony%2fconsole/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![passing](https://developer.mend.io/api/mc/badges/compatibility/packagist/symfony%2fconsole/6.4.4/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![confidence](https://developer.mend.io/api/mc/badges/confidence/packagist/symfony%2fconsole/6.4.4/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|| [symfony/process](https://symfony.com)([source](https://togithub.com/symfony/process)) | `6.4.4` -> `7.0.4` |[![age](https://developer.mend.io/api/mc/badges/age/packagist/symfony%2fprocess/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![adoption](https://developer.mend.io/api/mc/badges/adoption/packagist/symfony%2fprocess/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![passing](https://developer.mend.io/api/mc/badges/compatibility/packagist/symfony%2fprocess/6.4.4/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|[![confidence](https://developer.mend.io/api/mc/badges/confidence/packagist/symfony%2fprocess/6.4.4/7.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)|---### Release Notes<details><summary>symfony/console (symfony/console)</summary>### [`v7.0.4`](https://togithub.com/symfony/console/releases/tag/v7.0.4)[CompareSource](https://togithub.com/symfony/console/compare/v7.0.3...v7.0.4)**Changelog**(symfony/console@v7.0.3...v7.0.4)- bug[symfony/symfony#54009](https://togithub.com/symfony/symfony/issues/54009)\[Console] Fix display of vertical Table on Windows OS([@&#8203;VincentLanglet](https://togithub.com/VincentLanglet))- bug[symfony/symfony#54001](https://togithub.com/symfony/symfony/issues/54001)\[Console] Fix display of Table on Windows OS([@&#8203;VincentLanglet](https://togithub.com/VincentLanglet))- bug[symfony/symfony#53707](https://togithub.com/symfony/symfony/issues/53707)\[Console] Fix color support for TTY output([@&#8203;theofidry](https://togithub.com/theofidry))- bug[symfony/symfony#53711](https://togithub.com/symfony/symfony/issues/53711)\[Console] Allow false as a $shortcut in InputOption([@&#8203;jayminsilicon](https://togithub.com/jayminsilicon))### [`v7.0.3`](https://togithub.com/symfony/console/releases/tag/v7.0.3)[CompareSource](https://togithub.com/symfony/console/compare/v7.0.2...v7.0.3)**Changelog**(symfony/console@v7.0.2...v7.0.3)- bug[symfony/symfony#53516](https://togithub.com/symfony/symfony/issues/53516)\[Console] Allow '0' as a $shortcut in InputOption.php([@&#8203;lawsonjl-ornl](https://togithub.com/lawsonjl-ornl))- bug[symfony/symfony#53576](https://togithub.com/symfony/symfony/issues/53576)\[Console] Only execute additional checks for color support if theoutput ([@&#8203;theofidry](https://togithub.com/theofidry))### [`v7.0.2`](https://togithub.com/symfony/console/releases/tag/v7.0.2)[CompareSource](https://togithub.com/symfony/console/compare/v7.0.1...v7.0.2)**Changelog**(symfony/console@v7.0.1...v7.0.2)- bug[symfony/symfony#52940](https://togithub.com/symfony/symfony/issues/52940)\[Console] Fix color support check on non-Windows platforms([@&#8203;theofidry](https://togithub.com/theofidry))- bug[symfony/symfony#52941](https://togithub.com/symfony/symfony/issues/52941)\[Console] Fix xterm detection([@&#8203;theofidry](https://togithub.com/theofidry))### [`v7.0.1`](https://togithub.com/symfony/console/releases/tag/v7.0.1)[CompareSource](https://togithub.com/symfony/console/compare/v7.0.0...v7.0.1)**Changelog**(symfony/console@v7.0.0...v7.0.1)-   no significant changes### [`v7.0.0`](https://togithub.com/symfony/console/releases/tag/v7.0.0)[CompareSource](https://togithub.com/symfony/console/compare/v6.4.4...v7.0.0)**Changelog**(symfony/console@v7.0.0-RC2...v7.0.0)-   no significant changes</details><details><summary>symfony/process (symfony/process)</summary>### [`v7.0.4`](https://togithub.com/symfony/process/releases/tag/v7.0.4)[CompareSource](https://togithub.com/symfony/process/compare/v7.0.3...v7.0.4)**Changelog**(symfony/process@v7.0.3...v7.0.4)- bug[symfony/symfony#54006](https://togithub.com/symfony/symfony/issues/54006)\[Process] Fix the `command -v` exception (@&#8203;kayw-geek)- bug[symfony/symfony#53821](https://togithub.com/symfony/symfony/issues/53821)\[Process] Fix Inconsistent Exit Status in proc_get_status for PHPVersions Below 8.3 ([@&#8203;Luc45](https://togithub.com/Luc45))### [`v7.0.3`](https://togithub.com/symfony/process/releases/tag/v7.0.3)[CompareSource](https://togithub.com/symfony/process/compare/v7.0.2...v7.0.3)**Changelog**(symfony/process@v7.0.2...v7.0.3)- bug[symfony/symfony#53481](https://togithub.com/symfony/symfony/issues/53481)\[Process] Fix executable finder when the command starts with a dash([@&#8203;kayw-geek](https://togithub.com/kayw-geek))### [`v7.0.2`](https://togithub.com/symfony/process/releases/tag/v7.0.2)[CompareSource](https://togithub.com/symfony/process/compare/v7.0.0...v7.0.2)**Changelog**(symfony/process@v7.0.1...v7.0.2)- bug[symfony/symfony#52864](https://togithub.com/symfony/symfony/issues/52864)\[HttpClient]\[Mailer]\[Process] always pass microseconds to usleep asintegers ([@&#8203;xabbuh](https://togithub.com/xabbuh))### [`v7.0.0`](https://togithub.com/symfony/process/releases/tag/v7.0.0)[CompareSource](https://togithub.com/symfony/process/compare/v6.4.4...v7.0.0)**Changelog**(symfony/process@v7.0.0-RC2...v7.0.0)-   no significant changes</details>---### Configuration📅 **Schedule**: Branch creation - At any time (no schedule defined),Automerge - At any time (no schedule defined).🚦 **Automerge**: Enabled.♻ **Rebasing**: Whenever PR becomes conflicted, or you tick therebase/retry checkbox.🔕 **Ignore**: Close this PR and you won't be reminded about theseupdates again.---- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, checkthis box---This PR has been generated by [MendRenovate](https://www.mend.io/free-developer-tools/renovate/). Viewrepository job log[here](https://developer.mend.io/github/Lendable/composer-license-checker).<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4yMjAuMiIsInVwZGF0ZWRJblZlciI6IjM3LjIyMC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@nicolas-grekasnicolas-grekasnicolas-grekas approved these changes

@stofstofAwaiting requested review from stof

Assignees
No one assigned
Projects
None yet
Milestone
5.4
Development

Successfully merging this pull request may close these issues.

4 participants
@Luc45@carsonbot@nicolas-grekas@stof

[8]ページ先頭

©2009-2025 Movatter.jp