【问题标题】:Why does creating a neo4j.GraphDatabase from within a Paste app cause a segfault?为什么从粘贴应用程序中创建 neo4j.GraphDatabase 会导致段错误?
【发布时间】:2011-10-29 23:48:54
【问题描述】:

以下代码导致 Java 出现段错误:

import os.path
import neo4j
from paste import httpserver, fileapp
import tempfile
from webob.dec import wsgify
from webob import Response, Request

HOST = '127.0.0.1'
PORT = 8080

class DebugApp(object):
    @wsgify
    def __call__(self, req):

        # db = neo4j.GraphDatabase(tempfile.mkdtemp())
        db = neo4j.GraphDatabase(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data'))
        return Response(body='it worked')

def main():
    app = DebugApp()
    httpserver.serve(app, host=HOST, port=PORT)

if __name__ == '__main__':
    main()

要重现,首先将该代码保存到文件中(例如 app.py),然后运行 ​​python app.py。然后在浏览器中尝试http://localhost:8080;您应该会看到 Java 崩溃处理程序。

Java 堆栈跟踪的顶部如下所示:

Stack: [0xb42e7000,0xb4ae8000],  sp=0xb4ae44f0,  free space=8181k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [_jpype.so+0x26497]  JPJavaEnv::NewObjectA(_jclass*, _jmethodID*, jvalue*)+0x37
C  [_jpype.so+0x3c0e8]  JPMethodOverload::invokeConstructor(_jclass*, std::vector<HostRef*, std::allocator<HostRef*> >&)+0x178
C  [_jpype.so+0x3a417]  JPMethod::invokeConstructor(std::vector<HostRef*, std::allocator<HostRef*> >&)+0x47
C  [_jpype.so+0x1beba]  JPClass::newInstance(std::vector<HostRef*, std::allocator<HostRef*> >&)+0x2a
C  [_jpype.so+0x67b9c]  PyJPClass::newClassInstance(_object*, _object*)+0xfc
C  [python+0x96822]  PyEval_EvalFrameEx+0x4332
C  [python+0x991e7]  PyEval_EvalCodeEx+0x127

我相信那是 Python 中的 neo4j.GraphDatabase 触发 JPype 在 Java 下的 neo4j 中寻找 EmbeddedGraphDatabase

在交互式 Python 会话中运行此代码不会出现段错误:

>>> import webob
>>> import app
>>> debug_app = app.DebugApp()
>>> response = debug_app(webob.Request.blank('/'))
>>> response.body
'it worked'

大概是因为我在该示例中完全避免粘贴。也许这与 Paste 使用线程妨碍 neo4j 的方式有关?我在 neo4j 论坛中注意到了一个类似的问题:http://neo4j-community-discussions.438527.n3.nabble.com/Neo4j-CPython-Pylons-and-threading-td942435.html

...但这只发生在关机时。

【问题讨论】:

标签: python paste neo4j webob


【解决方案1】:

问题不在于 Paste 本身,而在于使用 JPype 的 neo4j Python 绑定。 Paste 创建线程来处理传入的请求; neo4j 应该是线程安全的,但是 JPype 附带了文档中的这个警告 (1):

“在大多数情况下,基于 OS 级别线程(即 posix 线程)的 python 线程将毫无问题地工作。唯一要记住的是在线程主体中调用 jpype.attachThreadToJVM() 以使 JVM 可以从那个线程。对于不是自己启动的线程,可以调用isThreadAttachedToJVM()来检查。"

我找不到执行此操作的代码,但我认为 neo4j 绑定中的一些 Java 代码可能会在导入时调用 attachThreadToJVM。如果是这样,当请求通过粘贴传递给工作线程,然后该线程去从 neo4j 获取数据时,它正在跨越线程边界,并且可能不满足 JVM 连接规则。

您可以通过仅在单个线程中运行import neo4j 来避免崩溃。在上面的例子中,这是 threading.Thread 所针对的可调用对象。

不幸的是,这意味着即使 neo4j 是线程安全的,但在 Python 中使用时必须将其限制为单个线程。但考虑到,这并不算太令人失望。

更新:维护人员回复(2)并调查了问题,并签入了修复程序。我不知道这是在哪个版本的 neo4j 中可用的,我再也找不到提交到他们的 github repo(3),所以这代表重新测试。

【讨论】:

  • 欢迎来到 StackOverflow。您可以/应该将此答案标记为已接受,以便其他人知道有解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
相关资源
最近更新 更多