On Arch Linux /lib is a symbolic link to /usr/lib. When the Python interpreter is provided with an argv[0] of e.g. '/python2.7' and the current working directory is /, it'll fail to start with the following error:
IOError: invalid Python installation: unable to open //include/python2.7/pyconfig.h (No such file or directory)
From what I understand, what is happening inside Modules/getpath.c is:
1) search_for_exec_prefix() is given an empty `argv0_path`
2) PYTHONHOME is not set, and we're not in a build directory, so step three is executed:
* Step 3. Try to find prefix and exec_prefix relative to argv0_path,
* backtracking up the path until it is exhausted. This is the most common
* step to succeed. Note that if prefix and exec_prefix are different,
* exec_prefix is more likely to be found; however if exec_prefix is a
* subdirectory of prefix, both will be found.
3) copy_absolute() sets `exec_prefix` to '/'
4) 'lib/python2.7' gets appended to `exec_prefix` using joinpath()
5) 'lib-dynload' gets appended to `exec_prefix` using joinpath()
6) '/lib/python2.7/lib-dynload' exists and the function returns 1 (success)
7) control is returned to calculate_path() which later reduces `exec_prefix` to '/'
During further initialization, sysconfig.py tries to open pyconfig.h, whose path is calculated as {exec_prefix}/include/python2.7/pyconfig.h; thus ending up with the nonexistent path //include/python2.7/pyconfig.h. The correct exec_prefix would be /usr.
Moreover, if argv[0] and/or the current working directory are one level deeper (or more), `exec_prefix` will not be reduced to '/' and search_for_exec_prefix() will proceed to step four:
* Step 4. Search the directories pointed to by the preprocessor variables
* PREFIX and EXEC_PREFIX. These are supplied by the Makefile but can be
* passed in as options to the configure script.
i.e.: If search_for_exec_prefix() is passed an `argv0_path` with the value '/mnt', step three will only check '/mnt' but not '/', because '/mnt' will be reduced to '' and the `while (exec_prefix[0])` condition will be false.
I see two problems with the behavior I describe above:
1) Step three will skip checking the root directory (/) if argv[0] or the current working directory are one or more levels below / (in other words, not directly under /). Its behavior in this regard is inconsistent.
2) When argv[0] is e.g. '/python2.7' and the current working directory is /, it'll use '/' as the exec_prefix and fail to start. The /lib -> /usr/lib symbolic link should get dereferenced and not used as is.
I'm not sure how this should be fixed, so I only tried to present the issue with as many details as I could. If something is unclear, let me know.
Lastly, search_for_prefix() has very similar code, so any fix will have to be applied there too.
(There is also a downstream bug report @ https://bugs.archlinux.org/task/30812.)
|