1

次のコードにより、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で、Javaの下でneo4j.GraphDatabaseJPypeが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

...しかし、それはシャットダウン時にのみ発生します。

4

1 に答える 1

3

問題はPaste自体ではなく、JPypeを使用するneo4jPythonバインディングにあります。貼り付けは、着信要求を処理するスレッドを作成します。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)へのコミットが見つからないため、これは再テストを意味します。

于 2011-11-01T16:09:55.050 に答える