lucene-pylucene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andi Vajda <va...@apache.org>
Subject Re: throwing an exception *through* Java?
Date Mon, 27 Sep 2010 01:20:52 GMT

On Sat, 25 Sep 2010, Bill Janssen wrote:

> Andi Vajda <vajda@apache.org> wrote:
>
>> On Sep 25, 2010, at 13:54, Bill Janssen <janssen@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.

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.

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.

Andi..

Mime
View raw message