New submission from Christian Ullrich:
I'm trying to do something that may be slightly tricky, and I think I just
found a vintage 1997 bug. Please correct me if I'm wrong.
This is PC/getpathp.c from current master:
430: static void
431: get_progpath(void)
432: {
433: extern wchar_t *Py_GetProgramName(void);
434: wchar_t *path = _wgetenv(L"PATH");
435: wchar_t *prog = Py_GetProgramName();
436:
437: #ifdef Py_ENABLE_SHARED
438: extern HANDLE PyWin_DLLhModule;
439: /* static init of progpath ensures final char remains \0 */
440: if (PyWin_DLLhModule)
441: if (!GetModuleFileNameW(PyWin_DLLhModule, dllpath, MAXPATHLEN))
442: dllpath[0] = 0;
443: #else
444: dllpath[0] = 0;
445: #endif
446: if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
447: return;
448: if (prog == NULL || *prog == '\0')
449: prog = L"python";
Lines 446-447 have been like this ever since Guido wrote them twenty years ago.
I think the logic is the wrong way around. As it is now, the function always
returns on line 447 because GetModuleFileNameW() *always* succeeds (returns
nonzero). Hence, everything below line 447 is dead code.
GetModuleFileNameW(NULL, ...) fills the buffer with the path to the executable
the current process was created from. It returns the number of characters put
into the buffer, or zero on error. However, the only way *this* call could fail
is if the code was being executed outside of any process, something that
clearly cannot happen.
Prior to August 1997, the relevant bit of code looked like this:
156: if (!GetModuleFileName(NULL, progpath, MAXPATHLEN))
157: progpath[0] = '\0'; /* failure */
This bug, if it is one, would only manifest when initializing an embedded
interpreter using a different argv[0] than that of the actual host process,
because if the host process is a python.exe, it very likely runs inside a
standard installation or venv anyway. What I am trying is to make an
interpreter running in a third-party host process take site-packages from a
venv.
Doing this (argv[0] different from actual host process) may not be entirely
proper itself, but then again, why would Py_SetProgramName() even exist
otherwise?
Suggested fix:
diff --git a/PC/getpathp.c b/PC/getpathp.c
index 8380e1bcfa..abb5e54c9f 100644
--- a/PC/getpathp.c
+++ b/PC/getpathp.c
@@ -443,8 +443,7 @@ get_progpath(void)
#else
dllpath[0] = 0;
#endif
- if (!GetModuleFileNameW(NULL, progpath, MAXPATHLEN))
- return;
+ GetModuleFileNameW(NULL, progpath, MAXPATHLEN);
if (prog == NULL || *prog == '\0')
prog = L"python";
Since the call to GetModuleFileNameW() cannot possibly fail, there is no real
point in checking its return value.
----------
components: Windows
messages: 301306
nosy: Christian.Ullrich, paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
status: open
title: Embedded initialization ignores Py_SetProgramName()
type: behavior
versions: Python 3.6, Python 3.7
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue31349>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com