Skip to content
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

#12068: Fix incorrect env handling in spawnProcess on Posix when posix_spawnp is used. #12069

Merged
merged 1 commit into from
Jan 24, 2024

Conversation

p12tic
Copy link
Contributor

@p12tic p12tic commented Dec 26, 2023

Fixes #12068. This is a regression starting at Twisted 23.8.0.

Documentation on reactor.spawnProcess says the following about env parameter:

env is None: On POSIX: pass os.environ

This was not correctly handled in os.posix_spawnp() code path.

Scope and purpose

This PR is just a simple one line fix to address #12068. Tests for environment passing on Posix have been added.

@p12tic p12tic force-pushed the 12068-fix-posix-spawnp-environ branch 2 times, most recently from e272748 to 76d08da Compare December 27, 2023 09:58
@p12tic
Copy link
Contributor Author

p12tic commented Dec 27, 2023

please review

@chevah-robot chevah-robot requested a review from a team December 27, 2023 10:06
@p12tic p12tic force-pushed the 12068-fix-posix-spawnp-environ branch from 76d08da to 7821139 Compare December 27, 2023 10:07
@adiroiban
Copy link
Member

Thanks for the PR!

Not sure what to do here.

I think that we should fix the documentation instead.

That is, the bug lies in the documentation and not in the code :)

This change was introduced 2 years ago and is present in a public release.

By doing this change, we will break backward compatibility.

The initial change from 16 years ago was using os.execvpe

https://github.com/twisted/twisted/blame/dee676b040dd38b847ea6fb112a712cb5e119490/src/twisted/internet/process.py#L468

My understanding is that execvpe always requires an explicit environment, and it will not copy the environment from the parent process.

Regards

@glyph
Copy link
Member

glyph commented Dec 27, 2023

Not sure what to do here.

I think that we should fix the documentation instead.

That is, the bug lies in the documentation and not in the code :)

This change was introduced 2 years ago and is present in a public release.

By doing this change, we will break backward compatibility.

The initial change from 16 years ago was using os.execvpe

Normally I would agree, except the circumstances under which posix_spawn is used are not entirely under control of the user, and this introduces an inconsistency within twisted's behaviors.

In this specific case, I think the least impactful thing is to fix the code, rather than the docs.

But perhaps we should shoot this over to the mailing list for a tiebreaker?

@p12tic p12tic force-pushed the 12068-fix-posix-spawnp-environ branch from 7821139 to a37d7f1 Compare December 28, 2023 08:57
@p12tic
Copy link
Contributor Author

p12tic commented Dec 28, 2023

This change was introduced 2 years ago and is present in a public release.

This change of behavior was actually released in 23.8.0 by enabling use of posix_spawnp. From release notes: "reactor.spawnProcess() now uses posix_spawnp when possible, making it much more efficient (#5710)"

The regression is actually pretty bad. It silently drops environment variables only under certain conditions (e.g. when path argument of spawnProcess is not specified). Which means that most of the uses of spawnProcess in a certain codebase will work, except a few which depend on environment variables and satisfy the conditions for using posix_spawnp. Additionally, spawnProcess is something that's usually mocked in unit tests. Which means that unit tests wouldn't catch the failure. Only full end to end or manual testing could possibly catch it. These naturally have much worse code coverage, which means that failures are likely to be unnoticed for quite some time.

This is how the bug was discovered in the first place - by investigating a regression in a downstream project caused by updating Twisted.

In this specific case, I think the least impactful thing is to fix the code, rather than the docs.

The code fix is needed in either case, because if we fix the docs, we need to adjust the behavior of how spawnProcess works in the case when regular fork is used.

@p12tic
Copy link
Contributor Author

p12tic commented Dec 28, 2023

My understanding is that execvpe always requires an explicit environment, and it will not copy the environment from the parent process.

execvpe uses os.environ when env argument is None. See here: https://github.com/python/cpython/blob/3.12/Lib/os.py#L594

Copy link
Member

@adiroiban adiroiban left a comment

Choose a reason for hiding this comment

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

Many thanks, Povilas for the PR and the explanations and investigation.

With the latest info, I also think that is best to fix the code.

I left a few minor comments regarding the scope/purpose of each test.

I tried to read the code, but I can't find why fork is expected to be used in those tests.

Please check my commend and add your feedback.

Other than that, this can be merged.

Once merged, I will try to trigger a new release.

Thanks again.

src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/newsfragments/12068.bugfix Outdated Show resolved Hide resolved
@p12tic
Copy link
Contributor Author

p12tic commented Dec 31, 2023

please review

@chevah-robot chevah-robot requested a review from a team December 31, 2023 11:20
@p12tic p12tic force-pushed the 12068-fix-posix-spawnp-environ branch 3 times, most recently from 5806332 to 83b03ba Compare January 3, 2024 14:50
Copy link
Member

@adiroiban adiroiban left a comment

Choose a reason for hiding this comment

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

Many thanks for the PR.

It looks good.

My only blocker for this PR is trying to use a dedicated reactor instance, rather than using the global reactor.

Maybe it's a bad suggestion :)

See my inline comments. Thanks!

src/twisted/test/test_process.py Outdated Show resolved Hide resolved
src/twisted/test/test_process.py Outdated Show resolved Hide resolved
Documentation on reactor.spawnProcess says the following about env
parameter:

env is None:  On POSIX: pass os.environ

This was not correctly handled in os.posix_spawnp() code path.
@p12tic p12tic force-pushed the 12068-fix-posix-spawnp-environ branch from 83b03ba to 90c56ab Compare January 24, 2024 16:36
@p12tic
Copy link
Contributor Author

p12tic commented Jan 24, 2024

please review

@chevah-robot chevah-robot requested a review from a team January 24, 2024 16:40
@p12tic
Copy link
Contributor Author

p12tic commented Jan 24, 2024

@adiroiban

Thanks a lot for your suggestions. I think I addressed all comments.

Copy link
Member

@glyph glyph left a comment

Choose a reason for hiding this comment

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

Looks great. Thanks for integrating all that feedback.

@glyph glyph enabled auto-merge January 24, 2024 16:46
@glyph glyph dismissed adiroiban’s stale review January 24, 2024 16:47

review comments addressed

@glyph glyph merged commit 11c9f58 into twisted:trunk Jan 24, 2024
23 checks passed
@p12tic p12tic deleted the 12068-fix-posix-spawnp-environ branch January 24, 2024 17:11
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.

spawnProcess() passes incorrect environment to subprocess when env=None and posix_spawnp() is used
5 participants