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

bpo-35537: subprocess can use posix_spawn with pipes #11575

Merged
merged 1 commit into from
Jan 23, 2019
Merged

bpo-35537: subprocess can use posix_spawn with pipes #11575

merged 1 commit into from
Jan 23, 2019

Conversation

vstinner
Copy link
Member

@vstinner vstinner commented Jan 16, 2019

  • subprocess.Popen can now also use os.posix_spawn() with pipes if
    pipe file descriptors are greater than 2.
  • Fix Popen._posix_spawn(): set _child_created to True.
  • Add Popen._close_pipe_fds() helper function to factorize the code.

https://bugs.python.org/issue35537

@vstinner
Copy link
Member Author

Follow-up of PR #11452.

@vstinner
Copy link
Member Author

@vstinner
Copy link
Member Author

PR rebased on top of PR #11579 (commit 0785889).

@pablogsal pablogsal self-requested a review January 16, 2019 14:34
file_actions = []
for fd in (p2cwrite, c2pread, errread):
if fd != -1:
file_actions.append((os.POSIX_SPAWN_CLOSE, fd))
Copy link
Contributor

Choose a reason for hiding this comment

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

Technically, there is no need to explicitly close parent pipe ends because they have O_CLOEXEC. One small advantage of doing that is to reduce the number of descriptors before the following dup2, which could increase their number (in a corner case when any of descriptors 0, 1, 2 is closed in the parent process) and potentially hit resource limits.

Copy link
Member Author

Choose a reason for hiding this comment

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

Technically, there is no need, but _posixsubprocess does that. In case of doubt, I prefer to mimick _posixsubprocess behavior.

    /* Close parent's pipe ends. */
    if (p2cwrite != -1)
        POSIX_CALL(close(p2cwrite));
    if (c2pread != -1)
        POSIX_CALL(close(c2pread));
    if (errread != -1)
        POSIX_CALL(close(errread));
    POSIX_CALL(close(errpipe_read));

Copy link
Member Author

Choose a reason for hiding this comment

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

If we decide to skip the close(), I would prefer to also modify _posixsubprocess. But here I only want to use posix_spawn() in more cases, so I prefer to not modify "unrelated" changes :-)

* subprocess.Popen can now also use os.posix_spawn() with pipes if
  pipe file descriptors are greater than 2.
* Fix Popen._posix_spawn(): set _child_created to True.
* Add Popen._close_pipe_fds() helper function to factorize the code.
@vstinner
Copy link
Member Author

PR rebased on top of PR #11579 (commit 0785889).

Since PR #11579, I rebased this PR again :-)

@vstinner
Copy link
Member Author

@gpshead @giampaolo: would you mind to review this change? It allows to use posix_spawn() in subprocess in much more cases.

@vstinner
Copy link
Member Author

If I don't get any feedback before the end of the week, I will just merge my PR. I prefer to merge it early during the 3.8 development cycle, to get more time to fix it if something goes wrong :)

os.close(errwrite)

if devnull_fd is not None:
os.close(devnull_fd)
Copy link
Contributor

Choose a reason for hiding this comment

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

In case of premature failure on X.Close() or os.close(X) the remaining pipes/fds will remain "open". Perhaps it makes sense to use contextlib.ExitStack.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is it a regression caused by my PR? Or a general remark on existing code? My PR just moves code, no?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, it doesn't look like a regression introduced by you (was already there).

Copy link
Member Author

Choose a reason for hiding this comment

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

At least, I factorized the code so it should help to enhance the code ;-) Maybe open an issue if you want to work on that? I don't see an obvious pattern to ensure that all file descriptors are properly closed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, makes sense. I bet there are many other places which can benefit from ExitStack in a similar manner.

@bedevere-bot
Copy link

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

Copy link
Member Author

@vstinner vstinner left a comment

Choose a reason for hiding this comment

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

@giampaolo: So what do you think of the overall change? :-)

os.close(errwrite)

if devnull_fd is not None:
os.close(devnull_fd)
Copy link
Member Author

Choose a reason for hiding this comment

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

At least, I factorized the code so it should help to enhance the code ;-) Maybe open an issue if you want to work on that? I don't see an obvious pattern to ensure that all file descriptors are properly closed.

Copy link
Contributor

@giampaolo giampaolo left a comment

Choose a reason for hiding this comment

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

LGTM

@vstinner vstinner merged commit f6243ac into python:master Jan 23, 2019
@vstinner vstinner deleted the subprocess_spawn2 branch January 23, 2019 18:00
@vstinner
Copy link
Member Author

@giampaolo: "LGTM"

Yay! Thanks for the approval! I merged my PR.

@vstinner
Copy link
Member Author

@giampaolo: As I wrote, please open a new issue if you would like to enhance the new _close_pipe_fds() helper method.

@giampaolo
Copy link
Contributor

@vstinner here it is: #11686

gpshead pushed a commit that referenced this pull request Jan 29, 2019
Close pipes/fds in subprocess by using ExitStack.

"In case of premature failure on X.Close() or os.close(X) the remaining pipes/fds will remain "open". Perhaps it makes sense to use contextlib.ExitStack."
- Rationale: #11575 (comment)
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.

5 participants