This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author chrullrich
Recipients chrullrich, paul.moore, steve.dower, tim.golden, zach.ware
Date 2017-09-05.12:45:00
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1504615500.56.0.927947330769.issue31349@psf.upfronthosting.co.za>
In-reply-to
Content
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.
History
Date User Action Args
2017-09-05 12:45:00chrullrichsetrecipients: + chrullrich, paul.moore, tim.golden, zach.ware, steve.dower
2017-09-05 12:45:00chrullrichsetmessageid: <1504615500.56.0.927947330769.issue31349@psf.upfronthosting.co.za>
2017-09-05 12:45:00chrullrichlinkissue31349 messages
2017-09-05 12:45:00chrullrichcreate