PyAudio에 대한 비동기 오디오 재생을 구현하고 있습니다. 백엔드 Portaudio는 자체 스레드를 생성하고 새로운 오디오 데이터가 필요할 때마다 C- 콜백 함수를 호출하여 비동기 재생을 구현합니다. 해당 C- 콜백 함수가 호출 될 때마다 사용자가 오디오 데이터를 제공해야하는 이전에 등록 된 Python 함수를 호출합니다.왜이 경우 PyGILState_Release (...)가 segfault입니까?
이 파이썬 호출이 파이썬이 아닌 스레드에서 발생하기 때문에 the documentation은 파이썬 호출 전에 PyGILState_Ensure()
을 호출해야하고 이후에는 PyGILState_Release()
을 호출해야한다고 말합니다. 그것은 대략 다음과 같습니다 PyGILState_Release(gstate)
에서 세그먼테이션 폴트 (segfault)
int stream_callback(const void *in, void* out, unsigned long frameCount,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData)
{
PyGILState_STATE gstate = PyGILState_Ensure();
/* create some python variables, as used below… */
py_result = PyObject_CallFunctionObjArgs(py_callback,
py_frameCount,
py_inTime,
py_curTime,
py_outTime,
py_inputData,
NULL);
/* evaluate py_result, do some audio stuff… */
PyGILState_Release(gstate);
return returnVal;
}
합니다. 이 콜백 함수는 매우으로 자주 호출됩니다. 몇 초에서 몇 백 번처럼 gstate
은 32 비트 변수이며 때로는 1
, 때로는 으로 설정됩니다. 1
으로 설정하면 충돌이 발생합니다. 일반적으로 하나의 1
과 2 ~ 4 개의 0
이옵니다.
이런 종류의 느낌은 PyGILState_Release(…)
이 실제로 돌아 오는 것보다 약간 더 오래 걸리므로 여전히 실행 중이거나 이와 비슷한 상황에서 호출됩니다. 충돌 때
는 스택 추적은 다음과 같습니다
#0 0x00007fff88c287b7 in pthread_mutex_lock()
#1 0x00000001001009a6 in PyThread_release_lock()
#2 0x00000001002efc82 in stream_callback (in=0x1014a4670, out=0x1014a4670, frameCount=4316612208, timeInfo=0x1014a4850, statusFlags=4297757032, userData=0x38) at _portaudiomodule.c:1554
#3 0x00000001004e3710 in AdaptingOutputOnlyProcess()
#4 0x00000001004e454b in PaUtil_EndBufferProcessing()
#5 0x00000001004e9665 in AudioIOProc()
#6 0x00000001013485d0 in dyld_stub_strlen()
#7 0x0000000101348194 in dyld_stub_strlen()
#8 0x0000000101346523 in dyld_stub_strlen()
#9 0x0000000101345870 in dyld_stub_strlen()
#10 0x000000010134aceb in AUGenericOutputEntry()
#11 0x00007fff88aa132d in HP_IOProc::Call()
#12 0x00007fff88aa10ff in IOA_Device::CallIOProcs()
#13 0x00007fff88aa0f35 in HP_IOThread::PerformIO()
#14 0x00007fff88a9ef44 in HP_IOThread::WorkLoop()
#15 0x00007fff88a9e817 in HP_IOThread::ThreadEntry()
#16 0x00007fff88a9e745 in CAPThread::Entry()
#17 0x00007fff88c5c536 in _pthread_start()
#18 0x00007fff88c5c3e9 in thread_start()
사람이 메이크업 감각을합니까?
당신이 링크 한 이슈는 PyEval_ReleaseLock과 관련이 없습니다 (사용되지 않기 때문에). 귀하의 문제는 아닙니다. 디버거에서 PyGILState_Release에서 segfault가 어디에서 발생하는지 정확히 알 수 있습니까?gstate 값 1은 파이썬이 아닌 스레드에서 호출 한 것을 나타내므로 임시 스레드 상태가 실제로 파괴되어 꽤 진행될 수 있습니다. – ncoghlan
또한 어떤 버전을 연결하고 있습니까? (GIL 코드가 3.2에서 상당히 바뀌었기 때문에 내가 보았던 버전이 달라졌습니다) – ncoghlan
파이썬 2.7.1 OSX로 작업하고 있습니다. – bastibe