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?

Bill

Reply via email to