[Jython-checkins] jython: No longer causes a stack overflow on "infinite reloads"
jim.baker
jython-checkins at python.org
Wed Dec 17 01:35:13 CET 2014
https://hg.python.org/jython/rev/8708596b329f
changeset: 7461:8708596b329f
user: Jim Baker <jim.baker at rackspace.com>
date: Tue Dec 16 17:34:50 2014 -0700
summary:
No longer causes a stack overflow on "infinite reloads"
Previously infinite_reload.py in test_import would cause a
RuntimeError due to a stack overflow. Now handles the same as CPython
by tracking which module is currently being reloaded, and returns
immediately with that module.
files:
src/org/python/core/PySystemState.java | 5 +-
src/org/python/core/imp.java | 26 ++++++++++++-
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/src/org/python/core/PySystemState.java b/src/org/python/core/PySystemState.java
--- a/src/org/python/core/PySystemState.java
+++ b/src/org/python/core/PySystemState.java
@@ -19,6 +19,7 @@
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.security.AccessControlException;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
@@ -131,7 +132,7 @@
public PyList argv = new PyList();
public PyObject modules;
- public PyObject modules_reloading;
+ public Map<String, PyModule> modules_reloading;
private ReentrantLock importLock;
private ClassLoader syspathJavaLoader;
public PyList path;
@@ -194,7 +195,7 @@
initialize();
closer = new PySystemStateCloser(this);
modules = new PyStringMap();
- modules_reloading = new PyStringMap();
+ modules_reloading = new HashMap<String, PyModule>();
importLock = new ReentrantLock();
syspathJavaLoader = new SyspathJavaLoader(imp.getParentClassLoader());
diff --git a/src/org/python/core/imp.java b/src/org/python/core/imp.java
--- a/src/org/python/core/imp.java
+++ b/src/org/python/core/imp.java
@@ -7,6 +7,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import org.python.compiler.Module;
@@ -1146,15 +1147,34 @@
}
static PyObject reload(PyModule m) {
+ PySystemState sys = Py.getSystemState();
+ PyObject modules = sys.modules;
+ Map<String, PyModule> modules_reloading = sys.modules_reloading;
+ ReentrantLock importLock = Py.getSystemState().getImportLock();
+ importLock.lock();
+ try {
+ return _reload(m, modules, modules_reloading);
+ } finally {
+ modules_reloading.clear();
+ importLock.unlock();
+ }
+ }
+
+ private static PyObject _reload(PyModule m, PyObject modules, Map<String, PyModule> modules_reloading) {
String name = m.__getattr__("__name__").toString().intern();
-
- PyObject modules = Py.getSystemState().modules;
PyModule nm = (PyModule) modules.__finditem__(name);
-
if (nm == null || !nm.__getattr__("__name__").toString().equals(name)) {
throw Py.ImportError("reload(): module " + name
+ " not in sys.modules");
}
+ PyModule existing_module = modules_reloading.get(name);
+ if (existing_module != null) {
+ // Due to a recursive reload, this module is already being reloaded.
+ return existing_module;
+ }
+ // Since we are already in a re-entrant lock,
+ // this test & set is guaranteed to be atomic
+ modules_reloading.put(name, nm);
PyList path = Py.getSystemState().path;
String modName = name;
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list