Project

Profile

Help

environ variable zero in one of SaxonProcessor methods crashes Python test

Added by Aleksandar Jelenak over 5 years ago

Hello!

A Python test resembling the @testXPathSingle@ in the @testXPath.cpp@ file causes a segmentation fault. A @jet_err@ file is generated with "@JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x...@" message. The information in the @jet_err@ file points to the @SaxonProcessor::getStringValue()@ method as the cause of the crash. This is the very first real Python test so don't know if others would have similar problems.

Since the Python interface is basically just wrapping the various C++ pointers returned by the Saxon/C library I thought that printing those pointer addresses would be a good way of tracking down what is happing in both the Python and C++ code. Here's the information I gathered:

The @testXPathSingle@ works when I compile the @testXPath.cpp@ file so the SIGSEGV occurs only in the Python test. The difference is that the @environ@ variable in the @SaxonProcessor::getStringValue()@ method is zero for the Python test and not zero for the @testXPath@ executable. This variable is not exposed to Python as I consider it holding internal state so don't know why it appears zero for one SaxonProcessor method.

Below is the debug information, first for the @testXPath@ executable:

C++: In SaxonProcessor::SaxonProcessor(bool l)
C++: l = 0
C++: refCount = 1
C++: before environ = 0
C++: after environ = 0xf1f7d0
C++: environ->myDllHandle = 0x7fbc2c206b40
C++: SaxonProcessor* = 0xf20b90
C++: In SaxonProcessor::newXPathProcessor()
C++: SaxonProcessor* = 0xf20b90
C++: environ = 0xf1f7d0

Test: XPathProcessor with Saxon version=Saxon-HE 9.6.0.9J from Saxonica

Test testXPathSingle:
C++: In SaxonProcessor::parseXmlFromString()
C++: SaxonProcessor* = 0xf20b90
C++: environ = 0xf1f7d0
C++: In XdmItem::size()
C++: XdmItem* = 0x124ef90
Number of items=1
C++: In XdmItem::getStringValue()
C++: SaxonProcessor* = 0xf20b90
C++: SaxonProcessor* = 0xf20b90
C++: In SaxonProcessor::getStringValue()
C++: SaxonProcessor* = 0xf20b90
C++: XdmItem* = 0x124ef90
C++: environ = 0xf1f7d0

Note the last line above, where the @environ@ variable holds a valid memory address. For the Python test, debug info below, that value is zero and, hence, the segmentation fault. The debug information without the "@C++:@" prefix comes from the Python interface.

In SaxonProcessor.__cinit__()
what = None
init = False
global _init = 1
C++: In SaxonProcessor::SaxonProcessor(bool l)
C++: l = 0
C++: refCount = 2
C++: before environ = 0x221c820
C++: SaxonProcessor* = 0x2d23cb0
SaxonProcessor* = 0x2d23cb0
In SaxonProcessor.newXPathProcessor()
SaxonProcessor* = 0x2d23cb0
before XPathProcessor* = (nil)
C++: In SaxonProcessor::newXPathProcessor()
C++: SaxonProcessor* = 0x2d23cb0
C++: environ = 0x221c820
after XPathProcessor* = 0x2c43810
In SaxonProcessor.parseXmlFromString()
SaxonProcessor* = 0x2d23cb0
before XdmNode* = (nil)
C++: In SaxonProcessor::parseXmlFromString()
C++: SaxonProcessor* = 0x2d23cb0
C++: environ = 0x221c820
after XdmNode* = 0x2e1fad0
In XPathProcessor.setContextItem()
XPathProcessor* = 0x2c43810
XdmItem* = 0x2e1fad0
In XPathProcessor.evaluate_single()
XPathProcessor* = 0x2c43810
before XdmItem* = (nil)
after XdmItem* = 0x2e1fca0
In Item.size
XdmItem* = 0x2e1fca0
C++: In XdmItem::size()
C++: XdmItem* = 0x2e1fca0
In Item.getStringValue()
XdmItem* = 0x2e1fca0
SaxonProcessor* = 0x2d23cb0
C++: In XdmItem::getStringValue()
C++: SaxonProcessor* = 0x2d23cb0
C++: SaxonProcessor* = 0x2d23cb0
C++: In SaxonProcessor::getStringValue()
C++: SaxonProcessor* = 0x2d23cb0
C++: XdmItem* = 0x2e1fca0
C++: environ = 0

The SIGSEGV crash occurs after this. What is strange is that if I comment out the offending line of code, the correct @environ@'s value appears again when destroying that same SaxonProcessor object at the end of the Python test:

In SaxonProcessor.__dealloc__()
SaxonProcessor* = 0x2d23cb0
global _init = 1
Destroying C++ SaxonProcessor*
C++: In SaxonProcessor::~SaxonProcessor()
C++: SaxonProcessor* = 0x2d23cb0
C++: refCount = 2
C++: environ = 0x221c820
C++: Reducing refCount by one
C++: refCount = 1

Included is the @jet_err@ file.


Replies (26)

RE: environ variable zero in one of SaxonProcessor methods crashes Python test - Added by O'Neil Delpratt over 5 years ago

Hi,

Interesting point you mention. The impact of the keyword virtual only shows up running the C++ under python. This might be down to differences in the compiler or there is something else that is needed in the python wrapper to make it aware of the C++ inheritance.

The basic details of virtual method can be found here: https://en.wikipedia.org/wiki/Virtual_function I found this article particularly useful with advanced details: http://web.stanford.edu/class/cs107l/handouts/07-Virtual-Functions.pdf

In essence, the evaluateSingle method from XPath returns a pointer to XdmItem. In the method and in the case of the example we go down the path where we create an object of the derived class XdmNode and return a pointer to the class as its base class XdmItem.

The addition of the keyword virtual in the XdmItem class for the method getStringValue means that we bound the method at runtime rather than at compile time therefore it is referencing via XdmNode object.

This still seems strange to me and worth investigating further since the only implementation of getStringValue is in the base class XdmItem.

(26-26/26)

Please register to reply