Message10892

Author amak
Recipients amak, yocaba
Date 2016-08-14.17:09:08
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1471194551.1.0.707939246088.issue2513@psf.upfronthosting.co.za>
In-reply-to
Content
> Is there currently a way to make the script evaluation thread-safe?

Script evaluation is already thread safe.

Furthermore, you have ensured thread safety of your code by using AtomicInteger and synchronization, etc, so that is not the problem.

The problem is that all of your threads are sharing the same output channel, and not synchronizing output to it. You would find exactly the same problem if jython was not involved at all. For example, if you run java code that uses System.out.print from multiple threads, then you will find the output of all of those threads to be interleaved, i.e. randomly mixed up.

There are two solutions to the problem.

1. Synchronize access to stdout, through some form of lock. You could, for example, provide a synchronized method that all scripts must use to generate output. That way, the output from multiple threads will be serialized, since only one thread at a time can have the synchronization lock.

2. Use a separate output channel for every thread. This is the preferred mechanism, because the output for every thread will appear on different channels, and there will be no need to figure out where the output comes from.

However, to do this, you must use the native PythonInterpreter constructor, rather than using PyScriptEngine.

All output channels are associated with a PySystemState object, which is essentially the equivalent of the python "sys" module, including sys.stdout and sys.stderr.

When a PythonInterpreter object is created, you can pass a PySystemState object to it, which means that it will have its own unique copy of sys.stdout and sys.stderr.

http://www.jython.org/javadoc/org/python/util/PythonInterpreter.html#PythonInterpreter(org.python.core.PyObject,%20org.python.core.PySystemState)

This is simple to do: see this code for example of how to do it.

https://hg.python.org/jython/file/tip/src/com/xhaus/modjy/ModjyJServlet.java#l109

Some notes.

1. This cannot be done through PyScriptEngine, which shares the same PySystemState object across all PythonInterpreters.

2. Using the builtin jython embedding machinery gives you far more control over your jython interpreters than PyScriptEngine, whose JSR 223 interface is generic to every embeddable language, and does not provide this level of fine control.

3. PythonInterpreter objects are fairly lightweight, so you don't need to be too concerned about using a lot of them, e.g. creating one for every user script that you evaluate and discarding it when finished.

Hope this helps,

Alan.
History
Date User Action Args
2016-08-14 17:09:11amaksetmessageid: <1471194551.1.0.707939246088.issue2513@psf.upfronthosting.co.za>
2016-08-14 17:09:11amaksetrecipients: + amak, yocaba
2016-08-14 17:09:10amaklinkissue2513 messages
2016-08-14 17:09:09amakcreate