It seems that when trying to use a Nimpy library from multiple Python threads, an error crashes the Python interpreter:
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
This error originates from compiled Nim code. The information I have on it so far:
- If a Nim extension is imported in the global scope, it can only be used from the main thread
- If an extension has been imported into the global scope, you cannot use it from another Python thread
- If an extension is imported into a running function's scope, it will still be bound to
sys.modules so when another thread tries to access it it will crash with the above error
- When using an extension in a non-main thread only, it will work (since it is only one thread)
- When using a Nim extension with Flask within a route handler, it will crash with the above error since each handler is executed in its own thread. Even handling subsequent requests after the initial one will crash even though it is on the same thread ID
- I tried duplicating a Nim extension
.so per thread, creating a unique Spec and Loader object and it successfully imports, but for some reason it still crashes likely due to the underlying C extension exposing the same module name (PyInit_<mod name>)
- The only solution I can come up with is to compile a separate Nim extension with a unique name per thread that should be used. This is just straight up hacky, however. A better solution probably exists.
Use this Nim module as a reference for the next 2 Python examples:
# calc.nim
import nimpy
proc add(a, b: int): int {.exportpy.} =
return a + b
Here is a code example that you can use the reproduce the problem:
import threading, nimporter
def foo():
import calc
print(calc.add(2, 20))
threading.Thread(target=foo).start()
threading.Thread(target=foo).start()
print('Here!')
Another example:
from flask import Flask
import nimporter
app = Flask(__name__)
@app.route('/')
def hello_world():
# Importing here instead of in global scope works for 1 request
import calc
return 'Hello ' + str(calc.add(2, 20))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
Unfortunately, it should be noted that this issue is beyond my current (2020) skillset so any assistance is appreciated if it will contribute towards a resolution.
It seems that when trying to use a Nimpy library from multiple Python threads, an error crashes the Python interpreter:
This error originates from compiled Nim code. The information I have on it so far:
sys.modulesso when another thread tries to access it it will crash with the above error.soper thread, creating a unique Spec and Loader object and it successfully imports, but for some reason it still crashes likely due to the underlying C extension exposing the same module name (PyInit_<mod name>)Use this Nim module as a reference for the next 2 Python examples:
Here is a code example that you can use the reproduce the problem:
Another example:
Unfortunately, it should be noted that this issue is beyond my current (2020) skillset so any assistance is appreciated if it will contribute towards a resolution.