Skip to content

Comments

bpo-34044: subprocess.Popen copies startupinfo#8090

Merged
vstinner merged 2 commits intopython:masterfrom
vstinner:startupinfo
Jul 5, 2018
Merged

bpo-34044: subprocess.Popen copies startupinfo#8090
vstinner merged 2 commits intopython:masterfrom
vstinner:startupinfo

Conversation

@vstinner
Copy link
Member

@vstinner vstinner commented Jul 4, 2018

subprocess.Popen now copy the startupinfo argument to leave it
unchanged: modify the copy, so the same startupinfo object can be
used multiple times.

https://bugs.python.org/issue34044

@vstinner
Copy link
Member Author

vstinner commented Jul 4, 2018

@segevfiner: Would you mind to review my change?

@vstinner
Copy link
Member Author

vstinner commented Jul 4, 2018

cc @eryksun

Copy link
Contributor

@segevfiner segevfiner left a comment

Choose a reason for hiding this comment

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

I remember starting to implement this when adding lpAttributeList, since it's a list, before I discovered that subprocess clobbers STARTUPINFO anyhow.

Copy link
Contributor

Choose a reason for hiding this comment

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

This does a deep copy. Maybe it's better to implement this using copy.deepcopy? (That's how I thought about doing it when I originally discovered that subprocess modifies the STARTUPINFO)

That way there will be no need to manually deep copy specific attributes by name below. You can just copy.deepcopy(self.lpAttributeList, memo). This should boil this entire method into one statement.

Copy link
Member Author

Choose a reason for hiding this comment

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

IMHO copy.deepcopy() is a bad practice. It seems like lpAttributeList can only contain one key, "handle_list", and the value of this key is always converted to a list in Popen (simplified code):

handle_list = list(attribute_list.get("handle_list", []))

Copy link
Member Author

Choose a reason for hiding this comment

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

copy.deepcopy() is only called 3 times in the whole stdlib... in dataclasses and mailbox.

Copy link
Contributor

Choose a reason for hiding this comment

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

I also came up with this alternative:

attribute_list = self.lpAttributeList.copy()
if 'handle_list' in attribute_list:
    attribute_list['handle_list'] = list(attribute_list['handle_list'])

It's shorter, and dict.copy might be faster than iterating and assigning to a new dict (I didn't check...) Use whichever one you like best. 😉

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this sounds better?

``subprocess.Popen`` now copies the ``startupinfo`` argument to leave it unchanged:
it will modify the copy, so that the same ``STARTUPINFO`` object can be used multiple times.

Not sure if core members add a Patch by note...

Copy link
Member Author

Choose a reason for hiding this comment

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

I used your version would sounds better.

Nah, I dislike crediting myself. Git can be used for statistics ;-)

subprocess.Popen now copies the startupinfo argument to leave it
unchanged: it will modify the copy, so that the same STARTUPINFO
object can be used multiple times.

Add subprocess.STARTUPINFO.copy() method.
@vstinner
Copy link
Member Author

vstinner commented Jul 5, 2018

I used git push --force to rewrite the commit message.

@vstinner
Copy link
Member Author

vstinner commented Jul 5, 2018

@segevfiner: Does the new version look better?

@vstinner
Copy link
Member Author

vstinner commented Jul 5, 2018

segevfiner approved these changes 7 minutes ago

Thank you for the review!

@vstinner vstinner merged commit 483422f into python:master Jul 5, 2018
@miss-islington
Copy link
Contributor

Thanks @vstinner for the PR 🌮🎉.. I'm working now to backport this PR to: 3.7.
🐍🍒⛏🤖 I'm not a witch! I'm not a witch!

@bedevere-bot
Copy link

GH-8120 is a backport of this pull request to the 3.7 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Jul 5, 2018
subprocess.Popen now copies the startupinfo argument to leave it
unchanged: it will modify the copy, so that the same STARTUPINFO
object can be used multiple times.

Add subprocess.STARTUPINFO.copy() method.
(cherry picked from commit 483422f)

Co-authored-by: Victor Stinner <[email protected]>
@vstinner
Copy link
Member Author

vstinner commented Jul 5, 2018

I don't think that it's ok to add a public STARTUPINFO.copy() method in 3.7.1, so I created a backport manually to make the method private: PR #8121.

vstinner added a commit that referenced this pull request Jul 5, 2018
subprocess.Popen now copies the startupinfo argument to leave it
unchanged: it will modify the copy, so that the same STARTUPINFO
object can be used multiple times.

Add subprocess.STARTUPINFO._copy() private method.

Python 3.7 backport from master makes the copy() private: renamed to
_copy().

(cherry picked from commit 483422f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants