Issue1426

classification
Title: JSR-223 support does take into consideration changes to the ScriptContext
Type: behaviour Severity: normal
Components: Core Versions: Deferred
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: nriley Nosy List: emblemparade, nriley, tuska
Priority: Keywords: patch

Created on 2009-08-06.05:19:44 by emblemparade, last changed 2010-02-04.15:43:23 by nriley.

Files
File name Uploaded Description Edit Remove
thread_locals.patch nriley, 2010-01-13.04:24:16 patch
thread_locals.patch nriley, 2010-01-21.00:37:15 better patch
Messages
msg4995 (view) Author: Tal (emblemparade) Date: 2009-08-06.05:19:43
In Subversion revision 6633.

The issue is that sometimes a ScriptEngine can be re-used, but called
with a different context. Why do this? Lots of reasons! In applications
that use scripts a lot, it's a waste of resources to recreate the
ScriptEngine all over again. Instead, it is reused, while only a
different context is used. This is how I've implemented in the
Scripturian project, and it works fine for every other JSR-223-compliant
engine supported (include Jython 2.2 with its JSR-223 support library).

This was quite easy to fix. I'm unsure how to submit a patch, but I hope
this will suffice! Here is PyScriptEngine with my addition:

    private Object eval(PyCode code, ScriptContext context) throws
ScriptException {
        try {
            interp.setIn(context.getReader());
            interp.setOut(context.getWriter());
            interp.setErr(context.getErrorWriter());
            List<Integer> scopes = context.getScopes();
            for (int scope : scopes) {
            	this.context.setBindings( context.getBindings( scope ),
scope );
            }
            return interp.eval(code).__tojava__(Object.class);
        } catch (PyException pye) {
            throw scriptException(pye);
        }
    }
msg4996 (view) Author: Tal (emblemparade) Date: 2009-08-06.13:14:22
On second look, three more fixes are needed to take account of the
context. First, in these two methods:

    private PyCode compileScript(String script, ScriptContext context)
throws ScriptException {
        try {
            String filename = (String)
context.getAttribute(ScriptEngine.FILENAME);
            List<Integer> scopes = context.getScopes();
            for (int scope : scopes) {
            	this.context.setBindings(context.getBindings(scope), scope);
            }
            if (filename == null) {
                return interp.compile(script);
            } else {
                return interp.compile(script, filename);
            }
        } catch (PyException pye) {
            throw scriptException(pye);
        }
    }

    private PyCode compileScript(Reader reader, ScriptContext context)
throws ScriptException {
        try {
            String filename = (String)
context.getAttribute(ScriptEngine.FILENAME);
            List<Integer> scopes = context.getScopes();
            for (int scope : scopes) {
            	this.context.setBindings(context.getBindings(scope), scope);
            }
            if (filename == null) {
                return interp.compile(reader);
            } else {
                return interp.compile(reader, filename);
            }
        } catch (PyException pye) {
            throw scriptException(pye);
        }
    }

Two problems with my patch: it is not thread-safe. Also, it alters the
engine's context and does not return it to its original value. I will
try to think of a way to make it better.

Finally, this method must be overridden to allow the engine context to
change:

    public void setContext(ScriptContext context) {
    	super.setContext(context);
    	interp.setLocals(new PyScriptEngineScope(this, context));
    }
msg5004 (view) Author: Nicholas Riley (nriley) Date: 2009-08-07.12:37:01
...which just makes eval even more expensive.  I'll take a look at this, 
thanks.
msg5007 (view) Author: Tal (emblemparade) Date: 2009-08-07.16:38:28
As it stands, the code does very little, but adding synchronization
would definitely slow things down. A better plan for thread safety is in
order!

Note that PyScriptEngineScope also synchronizes on the context, which
can be both bad for performance, and can also cause problems if
applications do their own work with the context.

Feel free to include me on your thoughts in this. I have a lot of
experience with JSR-223, and am very eager to get Jython 2.5 running
well in Scripturian!
msg5008 (view) Author: Nicholas Riley (nriley) Date: 2009-08-07.16:43:52
I did that synchronization because other JSR 223 implementations did.  If you 
could lay out a general idea of how it should work (or if you just want to fix 
it), let me know - patches gratefully accepted.  It's sometimes a bit hard to 
figure out from the JSR spec how these things actually get used.

I'm traveling this weekend but should be able to look at the ScriptContext 
issues on Monday.

Thanks!
msg5009 (view) Author: Tal (emblemparade) Date: 2009-08-07.16:55:47
I will give this some more thought. You're right about everything:
JSR-223 is a very loose spec (too loose). I've had serious problems
getting everything to work with Scripturian, and have even given up on a
few engines for some features. And, #2, even when they do work, they
solve thread-safety with simple synchronization.

Let's try together to make Jython's JSR-223 implementation better than
others. :)

Happy travels!
msg5365 (view) Author: Nicholas Riley (nriley) Date: 2009-12-09.08:44:11
This came up again on the mailing list:

http://article.gmane.org/gmane.comp.lang.jython.user/8466

It also brings up the various threading models described in JSR 223.  Should 
I implement a thread-isolated version or is it acceptable to create an engine 
per thread?  Python just has locals and globals, no "engine scope" and 
"global scope" and "thread scope" which JSR 223 wants...
msg5367 (view) Author: Tal (emblemparade) Date: 2009-12-09.15:00:07
The JSR is pretty terse when it comes to defining threading, but there
is a de-facto requirement which is obvious if one imagines use-cases
beyond the trivial. It must support multithreaded access to the
ScriptContext.

Here's a fact: without my patch, Jython breaks where are other JSR-223
implementations do not. Prudence now ships with my patched version:

http://threecrickets.com/prudence/

I didn't have time to work on this beyond my quick band aid. Nicholas,
what do you say? Do you want to take some time to work on this, or
should I try to slog through?

I tried, but got a bit frustrated as Jython SVN changed before my eyes
and broke my code... It seems this kind of work needs to be better
coordinated with the team. Also, there must be a multithreaded unit test
for this model, to make sure it doesn't break!
msg5368 (view) Author: Nicholas Riley (nriley) Date: 2009-12-09.18:42:05
Absolutely, I agree that the behavior with respect to bindings is a bug and 
correctness is more important than speed; let's just get there first.  My question 
was only whether it'd be useful to develop an engine with a different JSR 223 
threading model.

If you'd like to write a test case and propose a patch I'd be happy to review it.  If 
you have any questions, please ask on the mailing list or IRC.  I can spend some time 
on this after December 19.

Sorry about the Subversion changes.  I use git-svn to work on Jython so I can merge 
upstream changes easily; you could do the same.  The rate of change in Jython is 
actually relatively low so it's unlikely there will be another conflict in this area, 
however.
msg5370 (view) Author: Thomas Mortagne (tuska) Date: 2009-12-10.09:59:50
Side note: according to JSR 223 specs an engine is supposed to
automatically provide the script context as "context" binding but jython
doe snot seems to do it (since I'm reusing the same ScriptContext object
i was expecting to workaround this issue by doing context.mybinding)
msg5371 (view) Author: Nicholas Riley (nriley) Date: 2009-12-10.10:50:27
I don't understand what you mean.  Could you cite the specific section of 
the JSR 223 spec to which you're referring and/or give an example in code 
of what you are expecting to happen?
msg5372 (view) Author: Thomas Mortagne (tuska) Date: 2009-12-10.11:20:06
I mean when you are in your script, the variable "context" is supposed
to be the current ScriptContext object.

Here is the exact: "In all cases, the ScriptContext used during a script
execution must be a value in the Engine Scope of the ScriptEngine whose
key is the String “context”.". I found it in the PDF specs at
https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_JCP-Site/en_US/-/USD/ViewFilteredProducts-SimpleBundleDownload
and in all others JSR 223 implementations i seen
msg5401 (view) Author: Tal (emblemparade) Date: 2010-01-02.03:22:07
Here's a patch! I don't seem to have permissions to attach files to this
issue, so I am pasting it here.

The patch is quite invasive, by necessity. I had to change some things
in the way PythonInterpreter works, so that it could work with
thread-bound state.

It already had support for thread-bound PySystemState (with a small bug
that I fixed, for setIn, setOut and setErr). But it didn't have support
for thread-bound locals. To do this, I added support for threadLocals to
ThreadState, and then enabled an optional "threadLocals" mode for
PythonInterpreter. The result is that, in "threadLocals" mode, multiple
threads can use the same PythonInterpreter.

Now, for JSR-223, the issue is that the Python locals come from outside,
via the ScriptContext. We have no control for its thread-safety. Indeed,
the JSR-223 is silent on these matters. So, I removed all
synchronization from the PyScriptEngineScope code. If callers are using
us multi-threaded, it's up to them to protect things. (For example, they
can provide us with a thread-safe instance of ScriptContext.) In any
case, it was wrong to synchronize on the ScriptContext instance, since
it is external to us.

I hope this all makes sense.

-Tal


### Eclipse Workspace Patch 1.0
#P jython-trunk
Index: src/org/python/util/PythonInterpreter.java
===================================================================
--- src/org/python/util/PythonInterpreter.java	(revision 6958)
+++ src/org/python/util/PythonInterpreter.java	(working copy)
@@ -32,6 +32,8 @@
     protected PySystemState systemState;
 
     PyObject locals;
+    
+    protected boolean threadLocals = false;
 
     protected CompilerFlags cflags = new CompilerFlags();
 
@@ -83,8 +85,13 @@
         systemState.modules.__setitem__("__main__", module);
         locals = dict;
     }
+    
+    public void setThreadLocals(boolean threadLocals) {
+    	this.threadLocals = threadLocals;
+    }
 
     protected void setState() {
+    	// The thread-bound system state may not have been set yet for
this thread
         Py.setSystemState(systemState);
     }
 
@@ -95,7 +102,7 @@
      *            Python file-like object to use as input stream
      */
     public void setIn(PyObject inStream) {
-        systemState.stdin = inStream;
+    	Py.getSystemState().stdin = inStream;
     }
 
     public void setIn(java.io.Reader inStream) {
@@ -119,7 +126,7 @@
      *            Python file-like object to use as output stream
      */
     public void setOut(PyObject outStream) {
-        systemState.stdout = outStream;
+    	Py.getSystemState().stdout = outStream;
     }
 
     public void setOut(java.io.Writer outStream) {
@@ -137,7 +144,7 @@
     }
 
     public void setErr(PyObject outStream) {
-        systemState.stderr = outStream;
+    	Py.getSystemState().stderr = outStream;
     }
 
     public void setErr(java.io.Writer outStream) {
@@ -153,7 +160,7 @@
      */
     public PyObject eval(String s) {
         setState();
-        return __builtin__.eval(new PyString(s), locals);
+        return __builtin__.eval(new PyString(s), getLocals());
     }
 
     /**
@@ -161,7 +168,7 @@
      */
     public PyObject eval(PyObject code) {
         setState();
-        return __builtin__.eval(code, locals, locals);
+        return __builtin__.eval(code, getLocals(), getLocals());
     }
 
     /**
@@ -169,7 +176,7 @@
      */
     public void exec(String s) {
         setState();
-        Py.exec(Py.compile_flags(s, "<string>", CompileMode.exec,
cflags), locals, locals);
+        Py.exec(Py.compile_flags(s, "<string>", CompileMode.exec,
cflags), getLocals(), getLocals());
         Py.flushLine();
     }
 
@@ -178,7 +185,7 @@
      */
     public void exec(PyObject code) {
         setState();
-        Py.exec(code, locals, locals);
+        Py.exec(code, getLocals(), getLocals());
         Py.flushLine();
     }
 
@@ -187,7 +194,7 @@
      */
     public void execfile(String filename) {
         setState();
-        __builtin__.execfile_flags(filename, locals, locals, cflags);
+        __builtin__.execfile_flags(filename, getLocals(), getLocals(),
cflags);
         Py.flushLine();
     }
 
@@ -197,7 +204,7 @@
 
     public void execfile(java.io.InputStream s, String name) {
         setState();
-        Py.runCode(Py.compile_flags(s, name, CompileMode.exec, cflags),
locals, locals);
+        Py.runCode(Py.compile_flags(s, name, CompileMode.exec, cflags),
getLocals(), getLocals());
         Py.flushLine();
     }
 
@@ -225,11 +232,16 @@
 
 
     public PyObject getLocals() {
-        return locals;
+		return threadLocals ? Py.getThreadState().threadLocals : locals;
     }
 
     public void setLocals(PyObject d) {
-        locals = d;
+    	if(threadLocals) {
+    		Py.getThreadState().threadLocals = d;
+    	}
+    	else {
+    		locals = d;
+    	}
     }
 
     /**
@@ -242,7 +254,7 @@
      *            appropriate Python object.
      */
     public void set(String name, Object value) {
-        locals.__setitem__(name.intern(), Py.java2py(value));
+    	getLocals().__setitem__(name.intern(), Py.java2py(value));
     }
 
     /**
@@ -254,7 +266,7 @@
      *            the value to set the variable to
      */
     public void set(String name, PyObject value) {
-        locals.__setitem__(name.intern(), value);
+    	getLocals().__setitem__(name.intern(), value);
     }
 
     /**
@@ -265,7 +277,7 @@
      * @return the value of the variable, or null if that name isn't
assigned
      */
     public PyObject get(String name) {
-        return locals.__finditem__(name.intern());
+        return getLocals().__finditem__(name.intern());
     }
 
     /**
@@ -280,7 +292,7 @@
      * @return the value of the variable as the given class, or null if
that name isn't assigned
      */
     public <T> T get(String name, Class<T> javaclass) {
-        PyObject val = locals.__finditem__(name.intern());
+        PyObject val = getLocals().__finditem__(name.intern());
         if (val == null) {
             return null;
         }
Index: src/org/python/core/ThreadState.java
===================================================================
--- src/org/python/core/ThreadState.java	(revision 6958)
+++ src/org/python/core/ThreadState.java	(working copy)
@@ -24,6 +24,8 @@
     public TraceFunction tracefunc;
 
     public TraceFunction profilefunc;
+    
+    public PyObject threadLocals;
 
     private LinkedList<PyObject> initializingProxies;
 
Index: src/org/python/jsr223/PyScriptEngineScope.java
===================================================================
--- src/org/python/jsr223/PyScriptEngineScope.java	(revision 6958)
+++ src/org/python/jsr223/PyScriptEngineScope.java	(working copy)
@@ -38,15 +38,13 @@
     @ExposedMethod
     public PyObject scope_keys() {
         PyList members = new PyList();
-        synchronized (context) {
-            List<Integer> scopes = context.getScopes();
-            for (int scope : scopes) {
-                Bindings bindings = context.getBindings(scope);
-                if (bindings == null)
-                    continue;
-                for (String key : bindings.keySet())
-                    members.append(new PyString(key));
-            }
+        List<Integer> scopes = context.getScopes();
+        for (int scope : scopes) {
+            Bindings bindings = context.getBindings(scope);
+            if (bindings == null)
+                continue;
+            for (String key : bindings.keySet())
+                members.append(new PyString(key));
         }
         members.sort();
         return members;
@@ -63,12 +61,10 @@
     }
 
     public PyObject __finditem__(String key) {
-        synchronized (context) {
-            int scope = context.getAttributesScope(key);
-            if (scope == -1)
-                return null;
-            return Py.java2py(context.getAttribute(key, scope));
-        }
+        int scope = context.getAttributesScope(key);
+        if (scope == -1)
+            return null;
+        return Py.java2py(context.getAttribute(key, scope));
     }
 
     @ExposedMethod
@@ -77,12 +73,10 @@
     }
 
     public void __setitem__(String key, PyObject value) {
-        synchronized (context) {
-            int scope = context.getAttributesScope(key);
-            if (scope == -1)
-                scope = ScriptContext.ENGINE_SCOPE;
-            context.setAttribute(key, value.__tojava__(Object.class),
scope);
-        }
+        int scope = context.getAttributesScope(key);
+        if (scope == -1)
+            scope = ScriptContext.ENGINE_SCOPE;
+        context.setAttribute(key, value.__tojava__(Object.class), scope);
     }
 
     @ExposedMethod
@@ -91,11 +85,9 @@
     }
 
     public void __delitem__(String key) {
-        synchronized (context) {
-            int scope = context.getAttributesScope(key);
-            if (scope == -1)
-                throw Py.KeyError(key);
-            context.removeAttribute(key, scope);
-        }
+        int scope = context.getAttributesScope(key);
+        if (scope == -1)
+            throw Py.KeyError(key);
+        context.removeAttribute(key, scope);
     }
 }
Index: src/org/python/jsr223/PyScriptEngine.java
===================================================================
--- src/org/python/jsr223/PyScriptEngine.java	(revision 6958)
+++ src/org/python/jsr223/PyScriptEngine.java	(working copy)
@@ -2,9 +2,12 @@
 
 import java.lang.reflect.Method;
 import org.python.core.*;
+
 import java.io.Reader;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
+import java.util.List;
+
 import javax.script.AbstractScriptEngine;
 import javax.script.Bindings;
 import javax.script.Compilable;
@@ -21,20 +24,21 @@
 
     private final PythonInterpreter interp;
     private final ScriptEngineFactory factory;
-    private final PyModule module;
 
     PyScriptEngine(ScriptEngineFactory factory) {
         this.factory = factory;
-        interp = new PythonInterpreter(new PyScriptEngineScope(this,
context));
-        module =
(PyModule)Py.getSystemState().modules.__finditem__("__main__");
+        interp = new PythonInterpreter();
+        interp.setThreadLocals(true);
     }
-
+    
     public Object eval(String script, ScriptContext context) throws
ScriptException {
         return eval(compileScript(script, context), context);
     }
 
     private Object eval(PyCode code, ScriptContext context) throws
ScriptException {
         try {
+            // These affect states that are all thread-bound:
+            interp.setLocals(new PyScriptEngineScope(this, context));
             interp.setIn(context.getReader());
             interp.setOut(context.getWriter());
             interp.setErr(context.getErrorWriter());
@@ -67,6 +71,7 @@
     private PyCode compileScript(String script, ScriptContext context)
throws ScriptException {
         try {
             String filename = (String)
context.getAttribute(ScriptEngine.FILENAME);
+            interp.setLocals(new PyScriptEngineScope(this, context));
             if (filename == null) {
                 return interp.compile(script);
             } else {
@@ -80,6 +85,7 @@
     private PyCode compileScript(Reader reader, ScriptContext context)
throws ScriptException {
         try {
             String filename = (String)
context.getAttribute(ScriptEngine.FILENAME);
+            interp.setLocals(new PyScriptEngineScope(this, context));
             if (filename == null) {
                 return interp.compile(reader);
             } else {
@@ -93,6 +99,7 @@
     public Object invokeMethod(Object thiz, String name, Object...
args) throws ScriptException,
             NoSuchMethodException {
         try {
+            interp.setLocals(new PyScriptEngineScope(this, context));
             if (!(thiz instanceof PyObject)) {
                 thiz = Py.java2py(thiz);
             }
@@ -109,6 +116,7 @@
     public Object invokeFunction(String name, Object... args) throws
ScriptException,
             NoSuchMethodException {
         try {
+            interp.setLocals(new PyScriptEngineScope(this, context));
             PyObject function = interp.get(name);
             if (function == null) {
                 throw new NoSuchMethodException(name);
@@ -120,6 +128,7 @@
     }
 
     public <T> T getInterface(Class<T> clazz) {
+        PyModule module =
(PyModule)Py.getSystemState().modules.__finditem__("__main__");
         return getInterface(module, clazz);
     }
 
@@ -138,6 +147,7 @@
             new InvocationHandler() {
                 public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
                     try {
+                        interp.setLocals(new
PyScriptEngineScope(PyScriptEngine.this, context));
                         PyObject pyMethod =
thiz.__findattr__(method.getName());
                         if (pyMethod == null)
                             throw new
NoSuchMethodException(method.getName());
msg5402 (view) Author: Nicholas Riley (nriley) Date: 2010-01-02.14:15:09
Thanks!  I will look at this in the next couple days...
msg5403 (view) Author: Nicholas Riley (nriley) Date: 2010-01-02.19:08:12
Could you attach your patch? It's not applying because the lines wrapped.
msg5406 (view) Author: Tal (emblemparade) Date: 2010-01-05.03:00:43
Any luck? I'll just DropBox it for you:

http://dl.dropbox.com/u/122806/jsr223-patch.txt
msg5407 (view) Author: Tal (emblemparade) Date: 2010-01-05.03:00:46
Any luck? I'll just DropBox it for you:

http://dl.dropbox.com/u/122806/jsr223-patch.txt
msg5408 (view) Author: Nicholas Riley (nriley) Date: 2010-01-05.03:05:59
Thanks, that works... will look at it in the morning.
msg5424 (view) Author: Nicholas Riley (nriley) Date: 2010-01-12.02:29:53
I took a look at your patch. I'm not sure this is the right way to solve things, and I started on a better way but did not get finished in time. I will post what I have tomorrow; I think the best way to continue from there is to write some more detailed tests.
msg5425 (view) Author: Tal (emblemparade) Date: 2010-01-12.02:34:40
Sure, whatever you think best.

Keep in mind that the problem is not just for JSR-223, but for embedding Jython in general.
msg5426 (view) Author: Nicholas Riley (nriley) Date: 2010-01-12.02:41:33
Sure - I agree this is a useful feature for embedders, and I've kept it at the level of PythonInterpreter for the use of non-JSR 223 clients.

(Sorry to say "I'll post it tomorrow" but the code is on my laptop which has a dead battery and my charger is at work...)
msg5427 (view) Author: Tal (emblemparade) Date: 2010-01-12.02:43:46
Take your time! I'm just happy that this is taken seriously. I've been distributing a patched version of Jython with Prudence for far too long. Would be very nice to finally be in line with the main.
msg5430 (view) Author: Nicholas Riley (nriley) Date: 2010-01-13.04:24:16
Attached. I may be able to get back to this in the next week, but I can't promise anything.
msg5444 (view) Author: Nicholas Riley (nriley) Date: 2010-01-21.00:37:14
I made a bit more time (at the expense of many, many other things I should be doing...) to fix this up.  I think it's fine for JSR 223 purposes now.  At some point (probably March) I will refactor this so the thread-local behavior is in a PythonInterpreter subclass.  Another useful behavior for non-JSR 223 embedders, I think, would be to have shared globals and per-thread locals.

Do note that it doesn't create per-thread locals by default to preserve the existing behavior, but if you create a Bindings object and bind it, it should work.

I included a simple threaded test case.  If this doesn't work for you, it would help if you could modify ScriptEngineTest.java with a failing test case.

You can build & run this single test case class as follows:

ant -emacs singlejavatest -Dtest=ScriptEngineTest
msg5447 (view) Author: Tal (emblemparade) Date: 2010-01-21.06:41:37
Thanks for the taking the time, Nicholas. I'm surprised that embedded Jython isn't a common enough use case to make this a priority, but am glad for the attention!

Has your code been merged into trunk, or should I apply the patch?
msg5448 (view) Author: Nicholas Riley (nriley) Date: 2010-01-21.06:46:30
Nope, I haven't merged into trunk yet - waiting for feedback from you among other people :-)

I think a lot of the Jython embedders haven't caught up with 2.5 yet; we still get a lot of questions about 2.1 and 2.2.
msg5450 (view) Author: Nicholas Riley (nriley) Date: 2010-01-23.22:59:48
Committed in r6962.
msg5453 (view) Author: Tal (emblemparade) Date: 2010-01-24.20:11:23
Thanks, Nicholas. I am on a much-needed vacation and didn't have time to look at your patch, but will gladly evaluate and test when I get back.
msg5492 (view) Author: Tal (emblemparade) Date: 2010-02-04.13:54:53
Unfortunately, I can't get revision 6976 to work at all.

I'm getting an exception in the creation of the PythonPOSIXHandler. After some digging, I managed to spit out this stack trace:

java.lang.NoSuchFieldError: LoadNow
	at org.python.posix.POSIXFactory$1.<init>(POSIXFactory.java:13)
	at org.python.posix.POSIXFactory.<clinit>(POSIXFactory.java:11)
	at org.python.modules.posix.PosixModule.<clinit>(PosixModule.java:62)
	at org.python.modules.Setup.<clinit>(Setup.java:29)
	at org.python.core.PySystemState.initBuiltins(PySystemState.java:1001)
	at org.python.core.PySystemState.doInitialize(PySystemState.java:837)
	at org.python.core.PySystemState.initialize(PySystemState.java:756)
	at org.python.core.PySystemState.initialize(PySystemState.java:706)
	at org.python.core.PySystemState.initialize(PySystemState.java:699)
	at org.python.core.PySystemState.initialize(PySystemState.java:693)
	at org.python.core.PySystemState.initialize(PySystemState.java:689)
	at org.python.core.ThreadStateMapping.getThreadState(ThreadStateMapping.java:17)
	at org.python.core.Py.getThreadState(Py.java:1307)
	at org.python.core.Py.getThreadState(Py.java:1303)
	at org.python.core.Py.getSystemState(Py.java:1323)
	at org.python.util.PythonInterpreter.<init>(PythonInterpreter.java:102)
	at org.python.util.PythonInterpreter.threadLocalStateInterpreter(PythonInterpreter.java:77)
	at org.python.jsr223.PyScriptEngine.<init>(PyScriptEngine.java:27)
	at org.python.jsr223.PyScriptEngineFactory.getScriptEngine(PyScriptEngineFactory.java:85)
	at javax.script.ScriptEngineManager.getEngineByName(ScriptEngineManager.java:225)
msg5493 (view) Author: Nicholas Riley (nriley) Date: 2010-02-04.15:43:23
If r6974 works for you, I'm guessing the JFFI/ctypes merge broke something.  Please file a separate bug on this issue.
History
Date User Action Args
2010-02-04 15:43:23nrileysetmessages: + msg5493
2010-02-04 13:54:54emblemparadesetmessages: + msg5492
2010-01-24 20:11:23emblemparadesetmessages: + msg5453
2010-01-23 22:59:49nrileysetstatus: open -> closed
resolution: fixed
messages: + msg5450
2010-01-21 06:46:31nrileysetmessages: + msg5448
2010-01-21 06:41:38emblemparadesetmessages: + msg5447
2010-01-21 00:37:17nrileysetfiles: + thread_locals.patch
messages: + msg5444
2010-01-13 04:24:19nrileysetfiles: + thread_locals.patch
keywords: + patch
messages: + msg5430
2010-01-12 02:43:46emblemparadesetmessages: + msg5427
2010-01-12 02:41:34nrileysetmessages: + msg5426
2010-01-12 02:34:40emblemparadesetmessages: + msg5425
2010-01-12 02:29:54nrileysetmessages: + msg5424
2010-01-05 03:06:00nrileysetmessages: + msg5408
2010-01-05 03:00:46emblemparadesetmessages: + msg5407
2010-01-05 03:00:44emblemparadesetmessages: + msg5406
2010-01-02 19:08:12nrileysetmessages: + msg5403
2010-01-02 14:15:09nrileysetmessages: + msg5402
2010-01-02 03:22:12emblemparadesetmessages: + msg5401
2009-12-10 11:20:09tuskasetmessages: + msg5372
2009-12-10 10:50:27nrileysetmessages: + msg5371
2009-12-10 09:59:51tuskasetmessages: + msg5370
2009-12-10 09:50:28tuskasetnosy: + tuska
2009-12-09 18:42:06nrileysetmessages: + msg5368
2009-12-09 15:00:08emblemparadesetmessages: + msg5367
2009-12-09 08:44:12nrileysetmessages: + msg5365
2009-08-07 16:55:47emblemparadesetmessages: + msg5009
2009-08-07 16:43:52nrileysetmessages: + msg5008
2009-08-07 16:38:28emblemparadesetmessages: + msg5007
2009-08-07 12:37:02nrileysetassignee: nriley
messages: + msg5004
nosy: + nriley
2009-08-06 13:14:24emblemparadesetmessages: + msg4996
2009-08-06 05:19:44emblemparadecreate