#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 , 7 years ago
comment:2 by , 7 years ago
Sorted out a few things:
- Actual values of BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT are read with DosQueryExtLIBPATH and put into
os.environ
at Python process startup. os.putenv
understands BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT and properly callsDosSetExtLIBPATH
for them.os.putenv
is also used whenever theos.environ
dictionary is modified directly so doing so for those vars is also fine.os.putenv
, however, does not updateos.environ
with the new values of BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT, so bothos.getenv
andos.environ
continue 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.execve
filters 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.spawnve
nor my newos.spawn2
do the same. They should do it too, so a fix is needed.- After BEGINLIBPATH, ENDLIBPATH and LIBPATHSTRICT are filtered out by
os.execve
from 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.putenv
and 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.spawnve
andos.spawn2
don'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 cppunittest
in 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 , 7 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 , 7 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 , 7 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.environ
wrt to various calls where these vars are used. Will take some time to sort it out.BTW, I discovered when trying to run
mach cppunittest
in Firefox where it is needed to locate XUL.DLL in tests that are statically linked to it.