2011-12-17 17 views
0

a projectには、boost :: pythonとコールバック駆動の実行に関する問題があります。boost :: pythonとコールバック駆動型の実行

私のプロジェクトでは、C++のいくつかのPythonコードを実行するためにコールバックメカニズムが使用されています。

コールバックの実行を引き起こす最初の関数呼び出しがPythonインタプリタから来ている限り、すべて正常です。たとえば、

h = CallbackHandler() 

def mycallback(): 
    print "yeah" 

h.setCallback(mycallback) 

h.runCallback() 

# will print yeah 

名前:ああ、それは簡単ではありません。私のプロジェクトでは、オーディオ環境と通信するためにRtAudioが使用されています。 RtAudioの実行はコールバック駆動です:私はRtAudioにコールバック関数を与えます.RtAudioを起動すると、毎回サウンドを計算する必要があるたびにコールバックが呼び出されます。

RtAudioのコールバック・ドリブンの実行を使用している場合、私は、すぐに私のコードは、C++からPythonのコールバックを実行しようとするとセグメンテーション違反を取得します。

コールバック駆動型の実行を開始するには、非ブロッキングのstart()関数を呼び出す必要があります。これは、コールバック駆動の実行が別のスレッドで行われることを意味します。

次に、pythonからstart()を呼び出すときに、別にPythonの実行環境にアクセスする別のスレッドを作成しています。私はPythonのGILを少し理解しているので、これは良くありません。

このコールバック駆動型スレッドは、すべてを破損させることなく、Pythonコールバックを実行できるようにするにはどうすればよいですか?

申し訳ありませんが、私は私の問題... the problem is located thereの短い、完全に機能の例に私のコードを簡素化する方法を見つけることができませんでした。

EDIT

python documentationに周りを見た後、私は非PythonのスレッドがPython環境にアクセスしようとして作成されたときに、スレッドの安全性を扱うことになっている数行のコードを追加しました

gstate = PyGILState_Ensure(); 
while (!queue.empty() && queue.top()->next <= now) { 
    queue.top()->run(); 
    queue.pop(); 
} 
PyGILState_Release(gstate); 

しかし、私はまだsegfaultを取得します。だから私はvalgrindのを通してそれを走った、そしてここで私は(マイナス珍しいものvalgrindのは、常に「通常」である、Pythonインタプリタから取得)得るものです:

==31836== Thread 2: 
==31836== Invalid read of size 4 
==31836== at 0x41F0DD5: [email protected]@GLIBC_2.1 (in /lib/libpthread-2.14.1.so) 
==31836== by 0x5ED294C: callback(void*, void*, unsigned int, double, unsigned int, void*) (in /home/tom/Code/pyck/pyck/libcore.so) 
==31836== by 0x5F6B16B: RtApiAlsa::callbackEvent() (in /usr/lib/librtaudio.so) 
==31836== by 0x5F6BBCC: alsaCallbackHandler (in /usr/lib/librtaudio.so) 
==31836== by 0x42D286D: clone (in /lib/libc-2.14.1.so) 
==31836== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==31836== 
==31836== 
==31836== Process terminating with default action of signal 11 (SIGSEGV) 
==31836== Access not within mapped region at address 0x0 
==31836== at 0x41F0DD5: [email protected]@GLIBC_2.1 (in /lib/libpthread-2.14.1.so) 
==31836== by 0x5ED294C: callback(void*, void*, unsigned int, double, unsigned int, void*) (in /home/tom/Code/pyck/pyck/libcore.so) 
==31836== by 0x5F6B16B: RtApiAlsa::callbackEvent() (in /usr/lib/librtaudio.so) 
==31836== by 0x5F6BBCC: alsaCallbackHandler (in /usr/lib/librtaudio.so) 
==31836== by 0x42D286D: clone (in /lib/libc-2.14.1.so) 
==31836== If you believe this happened as a result of a stack 
==31836== overflow in your program's main thread (unlikely but 
==31836== possible), you can try to increase the size of the 
==31836== main thread stack using the --main-stacksize= flag. 
==31836== The main thread stack size used in this run was 8388608. 
==31836== 
==31836== HEAP SUMMARY: 
==31836==  in use at exit: 2,313,541 bytes in 2,430 blocks 
==31836== total heap usage: 22,140 allocs, 19,710 frees, 22,007,627 bytes allocated 
==31836== 
==31836== LEAK SUMMARY: 
==31836== definitely lost: 522 bytes in 5 blocks 
==31836== indirectly lost: 0 bytes in 0 blocks 
==31836==  possibly lost: 66,669 bytes in 1,347 blocks 
==31836== still reachable: 2,246,350 bytes in 1,078 blocks 
==31836==   suppressed: 0 bytes in 0 blocks 
==31836== Rerun with --leak-check=full to see details of leaked memory 
==31836== 
==31836== For counts of detected and suppressed errors, rerun with: -v 
==31836== Use --track-origins=yes to see where uninitialised values come from 
==31836== ERROR SUMMARY: 2703 errors from 196 contexts (suppressed: 83 from 13) 

私はそれが権利を取得した場合、私のコールバック関数がありますNULLポインタにアクセスしようとしていますか?

EDIT 2

[OK]を、私はこのすべてを発見しています。 pthread's documentationから、sem_post(sem)への呼び出しがあるように見えます。semはセマフォを指しています。しかし、それはNULLを指しています。

エラーをより正確に特定するにはどうすればよいですか?

+0

valgrindでプログラムを実行して、問題の原因をより正確に診断してください。 –

+0

@ John:valgrindの結果を追加 – girodt

+0

あなたのセマフォの問題は、使用しているキューの実装バグです。 – Omnifarious

答えて

0

あなたはGILと違反していると思います。私の推測では、コールバックコードはPythonインタプリタに入る前にGILを取得していないということです。

GILを使用するすべてのスレッドは、そうする前に登録する必要があります。そしてあなたのコールバックを実行しているスレッドは自分自身を登録していません。

C++コールバックがPythonコールバックを実行しないように設定します。代わりに、Pythonプログラムが読み込んでいるソケットに関連するデータを書き込みます。次に、Pythonプログラムは、ソケットから関連するデータを取得したときにコールバックを実行できます。

関連する問題