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
[EASY C] inherit the py launcher's STARTUPINFO #76741
Comments
I've occasionally seen requests to find the path of the LNK shortcut that was used to run a script -- for whatever reason. This can be reliably supported in most cases by calling WinAPI GetStartupInfo. If the flag STARTF_TITLEISLINKNAME is set, then the lpTitle field is the path to the LNK file. (This is how the console host process knows to use the shortcut file for its properties instead of the registry.) However, if .py scripts are associated with the py launcher, the STARTUPINFO that has the required information is in the launcher process instead of the python.exe process. Since to some extent the launcher is acting as a proxy for python.exe, I think it should initialize Python's STARTUPINFO from a copy of its own values as returned by GetStartupInfo. This solves the dwFlags and lpTitle problem. Additionally, the C runtime spawn family of functions supports inheriting file descriptors by passing them in the lpReserved2 field of STARTUPINFO. Currently this doesn't work when spawning Python via the launcher, since it calls CreateProcess instead of a spawn function. By inheriting the launcher's STARTUPINFO, this feature is restored as well. For example, in grandparent: >>> import os
>>> os.pipe()
(3, 4)
>>> os.set_inheritable(4, True)
>>> os.spawnl(os.P_WAIT, 'amd64/py_d.exe', 'py_d') grandchild (py_d.exe => python.exe): Python 3.7.0a4 (v3.7.0a4:07c9d85, Jan 9 2018, 07:07:02)
[MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.write(4, b'spam')
4
>>> ^Z grandparent: 0
>>> os.read(3, 4)
b'spam' |
This sounds like a good idea to me - feel free to contribute your PR. |
"inherit the py launcher's STARTUPINFO" I read the issue twice, and honestly I have no idea how to implement that. So I removed the "easy (C)" keyword. If you still consider that it's an "easy (C)" issue, please describe step by step how to implement it:
If you plan to use a pipe, it's tricky to make sure that the pipe is closed properly on both sides once STARTUPINFO is transferred. |
The "for example" line is the fix, it really is very simple. That said, we have no automatic validation for the launcher, and coming up with a good set of manual tests to check it is certainly not easy. |
Ah, so the task is just open PC/launcher.c and replaced "si.cb = sizeof(si)" with "GetStartupInfoW(&si)". Ok, I agree, that's easy and I would be happy to review such PR ;-) I add the "[EASY C]" tag to the issue title in this case. |
I am a new contributor, and happy to take this issue as my first contribution in cpython. I have sent a PR for the same. Please let me know if anything needs to be change. |
Hi Shiva, sorry for not noticing your PR earlier. I have one question for Eryk, who may be able to answer more easily than I can: do we need to initialize cbSize before calling GetStartupInfoW()? The docs[1] don't seem to suggest it, and I can't look at the implementation of that API until Monday, but perhaps you know? |
It should be fine. If the docs don't require initializing cb, we can assume it's done for us. For example, msvcrt.dll calls GetStartupInfo without initializing this field:
In x64, the first argument (lpStartupInfo) is in rcx. We see the DWORD (dd) value of cb is initially 0:
Continue to the ret[urn] instruction via pt and check that the returned value of cb is sizeof(*lpStartupInfo):
|
Oops, I forgot the check:
|
Great, thanks. I'll go ahead and merge. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: