03-17-06 12:46 PM
[ http://issues.apache.org/jira/brows...ON-114?page=all ]
Graham Dumpleton resolved MODPYTHON-114:
----------------------------------------
Fix Version: 3.3
Resolution: Fixed
> Problems with PythonPath directive.
> -----------------------------------
>
> Key: MODPYTHON-114
> URL: http://issues.apache.org/jira/browse/MODPYTHON-114
> Project: mod_python
> Type: Bug
> Components: core
> Versions: 3.1.4, 3.2.7
> Reporter: Graham Dumpleton
> Assignee: Graham Dumpleton
> Fix For: 3.3
>
> The "PythonPath" setting can be used to define the value of the Python "sy
s.path" variable. It is this variable which defines the list of directories
that Python will search in when looking for a module to be imported.
> Although the actual reassignment of "sys.path" by mod_python does not in i
tself present a problem due to assignment in Python being thread safe by def
inition, the context in which the assignment occurs is not thread safe and a
race condition exists.
> This exists as the top level mod_python dispatcher will consult the existing value
of "sys.path" and the last value for the "PythonPath" setting encountered before th
en making a decision to modify "sys.path". If multiple requests are being serviced i
n d
istinct threads within the context of the same interpreter instance, and eac
h at the same time decide they want to modify the value of "sys.path", only
one might ultimately succeed in setting it to the value it wants and any mod
ification required by the o
ther may be lost.
> In the worst case scenario, this can result in the importation of any subsequent m
odules within that request failing due to a required directory not being present in
"sys.path". It is possible that this situation may resolve itself and go away on a s
ubs
equent request, but due to how mod_python caches the last value of "PythonPath" in a global
variable this will be dependent on what other requests arrive.
> At the least, for mod_python to resolve the problem itself would require a request
to arrive in the interim which targeted the URL which was not the last to cache its
raw setting for "PythonPath". This only works though due to a further issue whereby
al
ternate requests against URLs with different "PythonPath" settings will caus
e "sys.path" to be extended everytime if the "PythonPath" setting references
"sys.path". This results in "sys.path" continually growing over time due to
directories being added mu
ltiple times.
> The problematic code in apache.py is:
> if config.has_key("PythonPath"):
> # we want to do as little evaling as possible,
> # so we remember the path in un-evaled form and
> # compare it
> global _path
> pathstring = config["PythonPath"]
> if pathstring != _path:
> _path = pathstring
> newpath = eval(pathstring)
> if sys.path != newpath:
> sys.path[:] = newpath
> To fix the problems, the processing of PythonPath directive should be protected by
a thread mutex lock and a dictionary should be used to store all seen values of Pyt
honPath rather than a single variable. If a value for PythonPath has ever been seen,
an
d not just from the last change, then no update would be necessary.
> if config.has_key("PythonPath"):
> try:
> _path_cache_lock.acquire()
> pathstring = config["PythonPath"]
> if not _path_cache.has_key(pathstring):
> newpath = eval(pathstring)
> _path_cache[pathstring] = None
> sys.path[:] = newpath
> finally:
> _path_cache_lock.release()
> There shouldn't really be a need to check whether the new path is differen
t to the current value of sys.path as that scenario shouldn't occur at that
point.
> The two parts of this problem were previously catalogued as ISSUE 15 and I
SSUE 16 in my list of problems with the module importing system. The list ca
n be found at:
> http://www.dscpl.com.au/articles/modpython-003.html
[ Post a follow-up to this message ]
|