GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — bpo-35537: use os.posix_spawn in subprocess by nanjekyejoannah · Pull Request #11242 · python/cpython

Conversation

@nanjekyejoannah

@nanjekyejoannah nanjekyejoannah commented Dec 19, 2018 •
edited by bedevere-bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This patch uses os.posix_spawn in subprocess.

posix_spawn() is faster but it's also safer: it allows us to do a lot of "actions" before exec(), before executing the new program. For example, you can close files and control signals.

@vstinner this is the patch without any options.

https://bugs.python.org/issue35537

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@nanjekyejoannah
use os.posix_spawn in subprocess
6726dac
@nanjekyejoannah
nanjekyejoannah requested a review from gpshead as a code owner December 19, 2018 16:17
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Dec 19, 2018
@bedevere-bot bedevere-bot added the awaiting review label Dec 19, 2018
@vstinner

vstinner commented Dec 19, 2018

Copy link
Copy Markdown
Member

@nanjekyejoannah: Thanks! Can you please open an issue on bugs.python.org to get a bug number? Then add "bpo-xxx: " to the title of your PR.

Can you also please add a NEWS entry? You can use the "blurb" tool: https://devguide.python.org/committing/#what-s-new-and-news-entries

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner
vstinner requested review from pablogsal and vstinner December 19, 2018 16:22
@nanjekyejoannah

nanjekyejoannah commented Dec 19, 2018

Copy link
Copy Markdown
Contributor Author

@vstinner ack. Am doing this shortly.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nanjekyejoannah nanjekyejoannah changed the title use os.posix_spawn in subprocess bpo-35537: use os.posix_spawn in subprocess Dec 19, 2018
vstinner
vstinner reviewed Dec 19, 2018
View reviewed changes
Comment thread Lib/subprocess.py Outdated
and not pass_fds
and cwd is None
and env is None
and restore_signals is False

@vstinner vstinner Dec 19, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

"and not restore_signals" would be better. I prefer to avoid "is" to compare with True/False.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
vstinner
vstinner reviewed Dec 19, 2018
View reviewed changes
Comment thread Lib/subprocess.py Outdated

def _posix_spawn(self, args, executable):
"""Execute program using os.posix_spawn()."""
env = dict(os.environ)

@vstinner vstinner Dec 19, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Is it really needeed to copy os.environ?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Dec 20, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I suggest to pass directly os.environ to os.posix_spawn().

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
vstinner
vstinner reviewed Dec 19, 2018
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2018-12-19-17-20-03.bpo-35537.z4E7aA.rst Outdated

@vstinner vstinner Dec 19, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

For better rendering (create links), I suggest:

Suggested change
subprocess.Popen can now use posix_spawn() in some cases.
:class:`subprocess.Popen` can now use :func:`os.posix_spawn` in some cases.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
vstinner
vstinner approved these changes Dec 19, 2018
View reviewed changes

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

LGTM, but I will wait until minor remarks are addressed.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot added awaiting merge and removed awaiting review labels Dec 19, 2018
izbyshev
izbyshev reviewed Dec 19, 2018
View reviewed changes
Comment thread Lib/subprocess.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

vstinner
vstinner requested changes Dec 20, 2018
View reviewed changes
Comment thread Lib/subprocess.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/subprocess.py Outdated

@vstinner vstinner Dec 20, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I suggest to pass (executable, args) to follow os.posix_spawn() API. The function has not return value, so I suggest to write instead:

Suggested change
return self._posix_spawn(args, executable)
self._posix_spawn(executable, args)
return

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/subprocess.py Outdated

def _posix_spawn(self, args, executable):
"""Execute program using os.posix_spawn()."""
env = dict(os.environ)

@vstinner vstinner Dec 20, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

I suggest to pass directly os.environ to os.posix_spawn().

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot removed the awaiting merge label Dec 20, 2018
@bedevere-bot

bedevere-bot commented Dec 20, 2018

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot added the awaiting changes label Dec 20, 2018
vstinner
vstinner reviewed Dec 20, 2018
View reviewed changes

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this 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 sentence to the Optimization section of Doc/whatsnew/3.8.rst? Something like:

"subprocess.Popen is now up to 60x faster on Linux and 106x faster on FreeBSD when os.posix_spawn() can be used."

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@serhiy-storchaka

serhiy-storchaka commented Dec 20, 2018

Copy link
Copy Markdown
Member

60x and 106x are from particular examples. If you use different examples (allocate 1 GiB or 4 GiB of memory in the parent) you can get different numbers. Concrete numbers depend on a program and do not have meaning without referring to concrete program.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

60x and 106x are from particular examples. If you use different examples (allocate 1 GiB or 4 GiB of memory in the parent) you can get different numbers. Concrete numbers depend on a program and do not have meaning without referring to concrete program.

It's hard to measure the average speedup, but IMHO it's nice to say that it can be way faster in some cases. So do you want to explain it differently? For example:

"subprocess.Popen is now up to 60x faster on Linux and 106x faster on FreeBSD when os.posix_spawn() can be used, the parent has large memory footprint (ex: 2 GiB), and the child process execution time is short."

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

@nanjekyejoannah: Until we agree on the sentence to be added to What's New in Python 3.8, don't add it. We can add it in the following PR.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@serhiy-storchaka

serhiy-storchaka commented Dec 20, 2018

Copy link
Copy Markdown
Member

I suggest to not use any precise numbers: "subprocess.Popen is now significantly faster" or "subprocess.Popen can be now tens times faster".

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nanjekyejoannah nanjekyejoannah closed this Dec 20, 2018
@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

@nanjekyejoannah It seems like you closed the PR. Was it on pupose? I'm unable to reopen the issue.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nanjekyejoannah

nanjekyejoannah commented Dec 20, 2018

Copy link
Copy Markdown
Contributor Author

@vstinner I will reopen did it by mistake.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nanjekyejoannah nanjekyejoannah reopened this Dec 20, 2018
@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

@nanjekyejoannah: this PR is now empty, it doesn't contain any commit :-( It seems like your removed your commit. You can use "git reflog" or open .git/logs/HEAD to recover your removed commit.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

nanjekyejoannah and others added 2 commits December 20, 2018 19:20
@nanjekyejoannah
use os.posix_spawn in subprocess
f7df9e8
@blurb-it
📜🤖 Added by blurb_it.
c05a078
vstinner
vstinner reviewed Dec 20, 2018
View reviewed changes
Comment thread Lib/subprocess.py Outdated

def _posix_spawn(self, args, executable):
"""Execute program using os.posix_spawn()."""
env = os.environ

@vstinner vstinner Dec 20, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

nitpick: this variable is useless, just pass directly os.environ to posix_spawn().

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
vstinner
vstinner approved these changes Dec 20, 2018
View reviewed changes

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

LGTM.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot added awaiting merge and removed awaiting changes labels Dec 20, 2018
@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

I will merge this PR tomorrow except if someone sees a good reason to not merge it: https://bugs.python.org/issue35537#msg332239

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

izbyshev
izbyshev reviewed Dec 20, 2018
View reviewed changes
Comment thread Lib/subprocess.py
and not start_new_session
and os.path.dirname(executable)
and self.stdin is self.stdout is self.stderr is None):
self._posix_spawn(args, executable)

@izbyshev izbyshev Dec 20, 2018

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Checking self.std* is still not enough. Those fields are for the parent's ends of pipes, but if a caller redirects to a descriptor, there is no such end. For example, subprocess.call(['/bin/sleep', '1000'], stdout=fd, close_fds=False, restore_signals=False) doesn't work properly.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@vstinner vstinner Dec 20, 2018

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

@izbyshev: Oh right! I fixed the test: test (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) instead of (self.stdin, self.stdout, self.stderr). Is it better now?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@izbyshev izbyshev Dec 21, 2018

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Yes, LGTM now.

There is another potential problem with posix_spawn: asynchronous error notification. _posixsubprocess uses a pipe to notify the parent about all errors up to and including execve errors, so its style is synchronous. Glibc and musl use the pipe-based notification too, but they are not required to do that, and I don't know what other implementations do.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@vstinner
Fix test deciding if posix_spawn() can be used
1b9357a
Test  (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
instead of (self.stdin, self.stdout, self.stderr).
@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

@nanjekyejoannah: I pushed directly a fix into your branch to fix the latest reported bug about standard streams ;-)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Dec 20, 2018

Copy link
Copy Markdown
Member

I will merge this PR tomorrow except if someone sees a good reason to not merge it: https://bugs.python.org/issue35537#msg332239

Hum, @izbyshev found another issue (already now fixed) with this PR. Since I will be offline next 2 weeks, I prefer to not merge yet since I would be unable to handle any issue caused by the change. I now prefer to wait until I'm back from holiday to merge the PR.

In the meanwhile, if another core dev feels brave enough to merge it, please go ahead ;-)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@nanjekyejoannah

nanjekyejoannah commented Dec 21, 2018

Copy link
Copy Markdown
Contributor Author

okay noted.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner

vstinner commented Dec 21, 2018 via email

Copy link
Copy Markdown
Member
I expect that posix_spawn() sets errno as does execv(). I tested a non existent executable and I got the expected exception and traceback. The pipe matters more when preexec_fn is used to return the Python traceback of the child and the exception type. But preeexec_fn doesn't make sense with (cannot be supported by) posix_spawn().
…
-- Night gathers, and now my watch begins. It shall not end until my death.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@izbyshev

izbyshev commented Dec 21, 2018

Copy link
Copy Markdown
Contributor

I expect that posix_spawn() sets errno as does execv()

As I explained, this behavior is not required by POSIX, and the opposite behavior is allowed. Recent glibc- and musl-based Linux behave as you expect, but for glibc, this was added in 2017. In my test on Ubuntu 14.04, ./python -c "import subprocess; subprocess.call(['/xxx'], close_fds=False, restore_signals=False)" silently returns with zero exit code.

FreeBSD also seems not to use any synchronous notification.

Other systems where posix_spawn is a syscall (macOS?) probably behave as you expect, but I've not checked.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner mentioned this pull request Jan 15, 2019
bpo-35537: subprocess uses os.posix_spawn in some cases #11452
Merged
@vstinner

vstinner commented Jan 16, 2019

Copy link
Copy Markdown
Member

I merged PR #11452 instead.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@vstinner vstinner closed this Jan 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@vstinner vstinner vstinner approved these changes
@gpshead gpshead Awaiting requested review from gpshead
@pablogsal pablogsal Awaiting requested review from pablogsal
+1 more reviewer
@izbyshev izbyshev izbyshev left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting merge

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

6 participants

@nanjekyejoannah @vstinner @bedevere-bot @serhiy-storchaka @izbyshev @the-knights-who-say-ni
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.