On Sep 27, 2010, at 11:17, Bill Janssen <jans...@parc.com> wrote:

Andi Vajda <va...@apache.org> wrote:

On Sat, 25 Sep 2010, Bill Janssen wrote:

Andi Vajda <va...@apache.org> wrote:

On Sep 25, 2010, at 13:54, Bill Janssen <jans...@parc.com> wrote:

I've got a subclass of PythonMultiFieldQueryParser. I'd like to be
able
to throw a custom Python exception with parameters in that code, and
catch it in the Python code that's using it.  To do this, the
exception
has to somehow travel through Java.  I thought I could perhaps
subclass
PythonException to do this, but it looks like that's not really an
extension class.

How to do this?

Have you tried just throwing your exception ? It should be picked up at the JVM crossing point and thrown on in some form back to Python,
no ?

Yep, it shows up again in Python as a JavaError, but the error type and any arguments associated with it have been stripped out. I'm trying to use it to communicate a really exceptional condition, and I need that
info.

The error reporting code is a bit tricky but if you're using shared mode -
the mode where the PythonException java class exists since it's part
of the JCC runtime shared library - a Python exception reported in an
extension class _should_ cross the VM boundaries back and forth (to
Java and then back to the original caller in Python) unadultered since
- unless there is a bug somewhere along the way - the Python error
state is not cleared until the stack has unwound to original call in
the Python interpreter.

You mean sys.exc_info() here?  Wouldn't that be clobbered by the
JavaError thrown by the JVM code?  Ah, but the JavaError I'm actually
seeing shouldn't be thrown at all.

The error you raise from your Python code is detected by the NULL
return value in the C++ extension code (JCC-generated) that calls your method. That NULL return value is then reported on to Java by throwing
a PythonException Java exception (line 1087 in functions.cpp).

This Java exception is then caught by one the call<something> macros
in JCCENv.cpp (line 447) which calls reportException() - in other
words, after every JNI method call, reportException() is called to
check for an exception raised in the JVM.

reportException(), JCCEnv.cpp line 407, checks to see if there is an
exception thrown in the JVM, checks it against PythonException and if
so throws the _EXC_PYTHON C++ exception which is turned into a NULL
return value by one of the OBJ_CALL()/INT_CALL() macros in macros.h,
line 17, which wrap every C++ call from Python (these macros also
release the GIL for the time of the call).

In other words, unless there is a bug or you're not using shared mode,
your Python exception state should not be getting lost. Then, I could
be missing something here, this code is a bit hairy as it uses three
language exception systems together across shared libraries.

Wonderfully twisty, but I follow.

Note also that there was a bug with this code in throwing C++
exception objects across shared libraries that I fixed in the latest
JCC by just throwing ints instead of C++ exception objects. If you're
not using the latest JCC release, you may be hitting this bug too.

That could be it.  I believe I'm using 2.9.3.  Is the fix in 3.0.2?

2.9.3, 3.0.2, 3.x and trunk all use jcc 2.6 so you should have that fix. Are you using shared mode ? (if you're seeing a java RuntimeException thrown, the answer is probably not).

Andi..


Bill

Reply via email to