#299 closed defect (fixed)
python: Special BEGINLIBPATH processing is broken
| Reported by: | dmik | Owned by: | |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | python | Version: | |
| Severity: | high | Keywords: | |
| Cc: |
Description
At least with subprocess.Popen() setting BEGINLIBPATH with either os.putenv or passing an env dictionary with this variable set has no effect. It used to work and could be broken by the latest subprocess changes (like r1281).
Change History (5)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
Sorted out a few things:
- Actual values of BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT are read with DosQueryExtLIBPATH and put into
os.environat Python process startup. os.putenvunderstands BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT and properly callsDosSetExtLIBPATHfor them.os.putenvis also used whenever theos.environdictionary is modified directly so doing so for those vars is also fine.os.putenv, however, does not updateos.environwith the new values of BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT, so bothos.getenvandos.environcontinue to return the old value (that was there at program startup). This is clearly wrong (inconsistent with the initialization behavior, at least) and needs to be fixed.os.execvefilters out BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT from the environment list passed to the underlying LIBC call (and down to DosExecPgm) to avoid confusing started programs as these vars are not real environment variables. However, neitheros.spawnvenor my newos.spawn2do the same. They should do it too, so a fix is needed.- After BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT are filtered out by
os.execvefrom the environment list, they are merely ignored, no calls to DosSetEXTLIBPATH are made. This means that passing these vars in the environment dict toos.execve(as opposed to e.g callingos.putenvand thenos.execv) has no effect on the started process (and it will fail to locate the DLL if the calling code relies on BEGINLIBPATH for that).os.spawnveandos.spawn2don't do filtering but they don't call DosSetEXTLIBPATH either. This is clearly wrong too and needs a fix. And this is the reason whymach cppunittestin Firefox fails — because it passes the path to XUL.DLL tosubprocess.Popen(which now usesos.spawn2) via the environment dict rather than viaos.putenv(which of course makes perfect sense).
comment:3 by , 8 years ago
Re 4, unfortunately, this is the documented behavior, see https://docs.python.org/2/library/os.html#os.environ. So I will leave it as is. This also means that in Python os.putenv, os.unsetenv should not be used directly: the os.environ dict should be always modified instead. Note that os.getenv(NAME) is basically an alias to os.environ[NAME] but there is a difference: os.getenv will return None if the requested variable does not exist but accessing os.environ[NAME] will throw an exception. In order to avoid the exception the dict should be accessed as os.environ.get(NAME, None) rather than by index.
comment:4 by , 8 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
5 and 6 are done in r1294 but only for os.execve and os.spawnve as for os.spawn2 it's better to be done in LIBCx to provide thread-safety in P_2_THREADSAFE mode. And since subprocess.Popen uses os.spawn2, Firefox has to wait for a LIBCx fix.
I also disabled polluting os.environ with unset BEGINLIBPATH/etc. values (appeared as empty strings there which makes no sense — a standard environment variable is deleted from the environment when assigned an empty string).
comment:5 by , 8 years ago
The LIBCx part is done in https://github.com/bitwiseworks/libcx/commit/5b911092f01b27aa326c129c6560e8f58f3aafa9. I had to do a bit more than just that; see the commit log.

Actually, it seems that it never worked right. As it's known, these vars are pseudo-vars and there is a broken mess of different approaches in attempts to sync these pseudo-vars with the contents of
os.environwrt to various calls where these vars are used. Will take some time to sort it out.BTW, I discovered when trying to run
mach cppunittestin Firefox where it is needed to locate XUL.DLL in tests that are statically linked to it.