Forums » Saxon/C Help and Discussions »
Need advice on how to use SaxonC 11.1 Python API in web application
Added by Martin Honnen almost 3 years ago
I started writing some more code using the Python API of SaxonC 11.1 HE and while command line programs run fine, any attempts to use similar code in a simple web application results in an error like "JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e" after the very first request.
I can't say I have lots of experience writing web applications in Python, so I might be doing something wrong but I would appreciate any advice on how/where to create/store the PySaxonProcessor object or how to organize the code to avoid the error.
A simple Python code is
"""
This script runs the application using a development server.
It contains the definition of routes and views for the application.
"""
from flask import Flask, request
app = Flask(__name__)
from saxonc import *
proc = PySaxonProcessor(license = False)
# Make the WSGI interface available at the top level so wfastcgi can get it.
wsgi_app = app.wsgi_app
@app.route('/')
def hello():
"""Renders a sample page."""
return "Hello World!"
@app.route('/xquery', methods=['POST'])
def xquery():
request_data = request.get_json()
result = evaluate_xquery(proc, request_data)
return result
def evaluate_xquery(proc, request_data):
xquery_processor = proc.new_xquery_processor()
if 'inputType' in request_data:
if request_data['inputType'] == 'xml':
input_node = proc.parse_xml(xml_text = request_data['inputData'])
xquery_processor.set_context(xdm_item = input_node)
elif request_data['inputType'] == 'json':
xquery_processor1 = proc.new_xquery_processor()
xquery_processor1.set_parameter('json-text', proc.make_string_value(request_data['inputData']))
input_json = xquery_processor1.run_query_to_value(query_text = 'declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; declare option output:method "adaptive"; declare variable $json-text as xs:string external; parse-json($json-text)')
xquery_processor.set_context(xdm_item = input_json.head)
result = xquery_processor.run_query_to_string(query_text = request_data['inputCode'])
return result
if __name__ == '__main__':
import os
HOST = os.environ.get('SERVER_HOST', 'localhost')
try:
PORT = int(os.environ.get('SERVER_PORT', '5555'))
except ValueError:
PORT = 5555
app.run(HOST, PORT)
The app starts fine and I can do a single request fine (at least as far as running the client code using JavaScript is concerned that does a fetch and receives a result:
fetch('/xquery', { method: 'POST', headers : { 'Content-Type' : 'application/json'} , body : JSON.stringify({inputCode : '?*', 'inputData' : '[1,2,3]', 'inputType' : 'json' }) }).then(response => response.text()).then(text => console.log(text))
gives <?xml version="1.0" encoding="UTF-8"?>1 2 3
but without any further requests the Python command console already shows
127.0.0.1 - - [11/Feb/2022 10:09:02] "←[37mPOST /xquery HTTP/1.1←[0m" 200 -
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e
Please, contact the vendor of the application.
Crash dump will be written to "C:\Users\marti\source\repos\SaxonCPythonAPI\SaxonCPythonAPI\jet_dump_27600.dmp"
Extra information about error is saved in the "jet_err_27600.txt" file.
ao the server handled the /xquery
request fine but then the JET runtime gives an error.
That text files starts as shown below, so it seems a memory access violation:
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e
Please, contact the vendor of the application.
Crash dump will be written to "C:\Users\marti\source\repos\SaxonCPythonAPI\SaxonCPythonAPI\jet_dump_27600.dmp"
Exception 0xC0000005 (EXCEPTION_ACCESS_VIOLATION) at 0x0000000000a6730e (C:\Program Files\Saxonica\SaxonCHE11.1\libsaxonhec.dll+0x66730e)
Failed to read memory at 0x0000009c0d9f0000
Version Information:
Java version: 1.8.0_181
Excelsior JET 15.30 Enterprise edition
JET Profile: OpenJDK version: 1.8.0_181; JET update level: 6; CPU architecture: amd64
Runtime: Server
CPU features: cmov mmx sse sse2 sse3 ssse3 sse4.1 sse4.2 avx avx2 fma f16c lzcnt popcnt bmi1 bmi2 adx cx8 cx16 movbe avx-512f
Application was deployed
Options and system properties:
-Djet.jit.disable.resolution=
-Djet.gc.heaplimit=0
-Djet.stack.trace=
Entry point type: Invocation API
Command line: "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\python.exe" "c:\program files\microsoft visual studio\2022\community\common7\ide\extensions\microsoft\python\core\debugpy" --connect 127.0.0.1:51423 --configure-subProcess False --configure-qt none --adapter-access-token 7eb4ea4aa456cafc14ab9e4d8167ff046cd2b609e8cd08916977861600df5764 C:\Users\marti\source\repos\SaxonCPythonAPI\SaxonCPythonAPI\app.py
OS:
Windows 10 build 19044
JET-compiled Components:
C:\Program Files\Saxonica\SaxonCHE11.1\libsaxonhec.dll dll, version info: jet-1530-mp1 (ent, en)
Replies (35)
Please register to reply
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
I have now tried to get rid of all the web api or web framework stuff and I have tried to use a simple Python multithreading app with SaxonC HE 11.2, it also gets that EXCEPTION_ACCESS_VIOLATION
:
import threading
import time
from saxonc import *
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter, saxon_proc):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
self.saxon_proc = saxon_proc
self.xquery_processor = saxon_proc.new_xquery_processor()
def run(self):
print ("Starting " + self.name)
example(self.name, self.counter, 5, self.xquery_processor)
print ("Exiting " + self.name)
def example(threadName, delay, counter, xquery_processor):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print(xquery_processor.run_query_to_string(query_text = '"Hello from SaxonC: " || current-dateTime()'))
counter -= 1
with PySaxonProcessor(license = False) as saxon_proc:
# Create new threads
thread1 = myThread(1, "Thread-1", 1, saxon_proc)
thread2 = myThread(2, "Thread-2", 2, saxon_proc)
# Start new Threads
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
Output:
SaxonProc constructor(l) called
SaxonProc constructor: jvm exists! jvmCreatedCPP=1
SaxonProc constructor(l) called
New processor created, Processor: -29383024
New processor created, Processor: -29383024
Starting Thread-1
Starting Thread-2
DEBUG: SaxonCAPI: param-name: qs, type of Value= java.lang.String
qs
<?xml version="1.0" encoding="UTF-8"?>Hello from SaxonC: 2022-03-05T11:35:18.791+01:00
DEBUG: SaxonCAPI: param-name: qs, type of Value= java.lang.String
qs
<?xml version="1.0" encoding="UTF-8"?>Hello from SaxonC: 2022-03-05T11:35:19.691+01:00
DEBUG: SaxonCAPI: param-name: qs, type of Value= java.lang.String
qs
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
That output on Windows at least shows that calling SaxonC works twice before crashing, on Linux it looks to go down earlier:
python3 Python3SimpleThreadingSaxonCHE112Ex1.py
Starting Thread-1
Starting Thread-2
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x00007ff275ebed49
Please, contact the vendor of the application.
Core dump will be written to "/mnt/wslg/dumps/core.%e"
Extra information about error is saved in the "jet_err_8068.txt" file.
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x00007ff275ebed49
Please, contact the vendor of the application.
Core dump will be written to "/mnt/wslg/dumps/core.%e"
Signal 11 (SIGSEGV)
siginfo: si_signo 11, si_errno 0, si_code 1, si_addr 0x000000000000000f
Version Information:
Java version: 1.8.0_181
Excelsior JET 15.30 Enterprise edition
JET Profile: OpenJDK version: 1.8.0_181; JET update level: 6; CPU architecture: amd64
Runtime: Server
CPU features: cmov mmx sse sse2 sse3 ssse3 sse4.1 sse4.2 avx avx2 fma f16c lzcnt popcnt bmi1 bmi2 adx cx8 cx16 movbe
Application was deployed
Options and system properties:
-Djet.jit.disable.resolution=
-Djet.gc.heaplimit=0
-Djet.stack.trace=
Entry point type: Invocation API
Command line: "python3" "Python3SimpleThreadingSaxonCHE112Ex1.py"
OS:
Ubuntu 20.04.4 LTS
Linux 5.10.60.1-microsoft-standard-WSL2 #1 SMP Wed Aug 25 23:20:18 UTC 2021 x86_64
glibc 2.31
JET-compiled Components:
/usr/lib/libsaxonhec.so dll, version info: jet-1530-mp1 (ent, en)
Is there any unit test trying to use SaxonC 11 with Python and multithreading?
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
Now tried to run the Linux Python multithreading stuff in gdb, log is
gdb) run Python3SimpleThreadingSaxonCHE112Ex1.py
Starting program: /usr/bin/python3 Python3SimpleThreadingSaxonCHE112Ex1.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3e21700 (LWP 11271)]
[New Thread 0x7ffff3620700 (LWP 11272)]
[Thread 0x7ffff3620700 (LWP 11272) exited]
[New Thread 0x7ffff2e0b700 (LWP 11273)]
[New Thread 0x7ffff2bed700 (LWP 11274)]
[New Thread 0x7ffff298d700 (LWP 11275)]
[New Thread 0x7ffff296f700 (LWP 11276)]
[New Thread 0x7ffff2951700 (LWP 11277)]
[New Thread 0x7ffff2933700 (LWP 11278)]
[New Thread 0x7ffff2915700 (LWP 11279)]
[New Thread 0x7ffff28f7700 (LWP 11280)]
[New Thread 0x7ffff28d9700 (LWP 11281)]
[New Thread 0x7ffff28bb700 (LWP 11282)]
[New Thread 0x7ffff289d700 (LWP 11283)]
[New Thread 0x7ffff21dc700 (LWP 11284)]
[New Thread 0x7ffff20fa700 (LWP 11285)]
[New Thread 0x7ffff2018700 (LWP 11286)]
[New Thread 0x7ffff1dc3700 (LWP 11287)]
[New Thread 0x7ffff1ae1700 (LWP 11288)]
[New Thread 0x7ffff3620700 (LWP 11289)]
Starting Thread-1
[New Thread 0x7ffff17ff700 (LWP 11290)]
Starting Thread-2
Thread 20 "python3" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff3620700 (LWP 11289)]
0x00007ffff3e7fd49 in ?? () from /usr/lib/libsaxonhec.so
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
With the DEBUG flag enabled under Linux I get the following exception java.lang.StackOverflowError
:
python3 Python3SimpleThreadingSaxonCHE112Ex1.py
SaxonProc constructor(l) called
SaxonProc constructor: jvm exists! jvmCreatedCPP=1
SaxonProc constructor(l) called
New processor created, Processor: 550045968
New processor created, Processor: 550045968
Starting Thread-1
Starting Thread-2
Exception in thread "main" java.lang.StackOverflowError
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by O'Neil Delpratt over 2 years ago
Hi Martin,
Thank you for your posts. I will look carefully at your multithreading examples ASAP. Python web apps that work with multithreading is under tested.
Tips
-
Not to use Context manager (i.e.
with
) in multi-threaded applications as the release method may be called before a thread is done. This also applies to in Flask. -
In Flask applications it is best to cache the
PySaxonProcessor
object so that it can be used throughout the application.
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
I have tried the multithreading code without with
, it is
import threading
import time
from saxonc import *
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter, xquery_processor):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
self.xquery_processor = xquery_processor
def run(self):
print ("Starting " + self.name)
example(self.name, self.counter, 5, self.xquery_processor)
print ("Exiting " + self.name)
def example(threadName, delay, counter, xquery_processor):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print("%s : %s" % (threadName, xquery_processor.run_query_to_string(query_text = '"Hello from SaxonC: " || current-dateTime()')))
counter -= 1
saxon_proc = PySaxonProcessor(license = False)
# Create new threads
thread1 = myThread(1, "Thread-1", 1, saxon_proc.new_xquery_processor())
thread2 = myThread(2, "Thread-2", 2, saxon_proc.new_xquery_processor())
# Start new Threads
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
saxon_proc.release()
but (tested on Windows) fails with the same
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e
Please, contact the vendor of the application.
Crash dump will be written to "C:\Users\marti\source\repos\PythonMultiThreadingSaxonCHE112NoWithTest1\PythonMultiThreadingSaxonCHE112NoWithTest1\jet_dump_1504.dmp"
Exception 0xC0000005 (EXCEPTION_ACCESS_VIOLATION) at 0x0000000000a6730e (C:\Program Files\Saxonica\SaxonC HE 11.2\libsaxonhec.dll+0x66730e)
Failed to read memory at 0x000000a2b1240000
after calling each thread's method once:
Starting Thread-1
Starting Thread-2
Thread-1 : <?xml version="1.0" encoding="UTF-8"?>Hello from SaxonC: 2022-03-06T12:30:23.362+01:00
Thread-2 : <?xml version="1.0" encoding="UTF-8"?>Hello from SaxonC: 2022-03-06T12:30:24.339+01:00
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: system exception at 0x0000000000a6730e
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by O'Neil Delpratt over 2 years ago
Thanks Martin for reporting this issue. I have reproduced it on my linux machine. Created the following bug issue to keep track of its progress: https://saxonica.plan.io/issues/5373
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by O'Neil Delpratt over 2 years ago
Hi Martin,
The bug issue #5373 is now resolved, I have since turned my attention to running SaxonC on Flask. I am now getting a response with the simple example app you posted here: https://saxonica.plan.io/boards/4/topics/8523?r=8608#message-8608
After a few requests the server crashes as follows:
JET RUNTIME HAS DETECTED UNRECOVERABLE ERROR: runtime error
Thread 33B13 ["Thread-1"] is terminated without notifying the JVM. Probably, "DetachCurrentThread" function was not called
Please, contact the vendor of the application.
Core dump will be piped to "/usr/share/apport/apport %p %s %c %d %P %E"
Extra information about error is saved in the "jet_err_211711.txt" file.
Aborted (core dumped)
I did expect this kind of error. I am wondering where we can add the call to detach_current_thread
.
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by Martin Honnen over 2 years ago
Hi,
thanks for looking into this. I am afraid I have no immediate idea on where/how to use your resolution of that multithreading bug and the addition of the detatch_current_thread
to write a well working flask app, mainly because I don't know details as to when a request results in a new thread handling it or a request terminates a thread with flask, partly of course because I will probably need to run/test the API addition to understand its use reasonable well.
The general advice was also to make sure the PySaxonProcessor is stored/cached but even there I have not made progress as it seems so far that all kind of stores/caches the framework provides wants cacheable/storable objects to be kind of JSON serializable.
I am not sure how to proceed, if you want to release Saxon 11.3 perhaps it is better to leave this issue open and at least have a new release were basic multithreading using Saxon in Python works in a controlled way before looking for further improvements to find ways to control it inside of a more complex web application.
I will see whether I can write some test code over the weekend to get a better understanding of where/when Flask creates a new thread or terminates an existing one, will also look at the documentation whether it illuminates about the use of threads. Before that I don't have a good suggestion as to where to call detach_current_thread
, I don't know whether I will have a good suggestion after doing some tests, we'll see.
RE: Need advice on how to use SaxonC 11.1 Python API in web application - Added by O'Neil Delpratt over 2 years ago
I have resolved the issue of calling the detach_current_thread
. I found this article helpful: https://flask.palletsprojects.com/en/2.0.x/appcontext/
In particular the details about teardown_X
:
teardown_X() closes or otherwise deallocates the resource if it exists. It is registered as a teardown_appcontext() handler.
In the example I added the following:
@app.teardown_appcontext
def teardown_saxonc_thread(exception):
proc.detach_current_thread
All requests now run without crashing.
- « Previous
- 1
- 2
- Next »
Please register to reply