2010-03-19 5 views
4

나는 제거 할 수없는 segfault를 만드는 아주 잘린 예제가 있습니다. 파이썬 스크립트는 확장 기능에서 C 함수를 호출하여 pthreads를 사용하여 새 스레드를 만듭니다. PyGILState_Ensure 및 PyGILState_Release 내 파이썬 호출 (PyRun_SimpleString) 새 스레드에서 사용하지만, 아마도 제대로 사용하지 않는 또는 다른 단계를 놓친. receive_audio 함수에서 파이썬 호출을 주석 처리하면 더 이상 segfault가 발생하지 않습니다. 어떤 아이디어?Segfault가 멀티 스레드 파이썬 확장 C 언어로

출력 :

파이썬 lib 디렉토리/test.py
(메인 스레드) initmodule 완전한
(메인 스레드)를 호출 run_thread()
(메인 스레드) 만들기 스레드
receive_audio에서 (새 스레드)() - GIL 획득
(새 스레드) python print!

PyMODINIT_FUNC streamaudio() { 
    PyObject *m = Py_InitModule("streamaudio", methods); 
    PyEval_InitThreads(); 
    mainThreadState = PyThreadState_Get(); 
    PyEval_ReleaseLock(); 
    printf("(Main Thread) initmodule complete\n"); 
} 

static PyObject* run_thread(PyObject* self, PyObject* args) 
{ 
    int ok, stream_id; 
    PyGILState_STATE gstate; 
    gstate = PyGILState_Ensure(); 
    ok = PyArg_ParseTuple(args, "i", &stream_id); 
    PyRun_SimpleString("print '(Main Thread) Creating thread'\n"); 
    int rc = pthread_create(&thread, NULL, receive_audio, (void*)stream_id); 
    PyRun_SimpleString("print '(Main Thread) Thread created'\n"); 
    PyGILState_Release(gstate); 
    return Py_BuildValue("i", rc); 
} 

void* receive_audio(void *x) 
{ 
    printf("(New Thread) In receive_audio() - acquiring GIL\n"); 
    PyGILState_STATE gstate; 
    gstate = PyGILState_Ensure(); 
    PyRun_SimpleString("print '(New Thread) python print!'\n"); 
    PyGILState_Release(gstate); 
    printf("(New Thread) In receive_audio() - released GIL\n"); 
    int i; 
    for (i = 0; i < 100; i++) { 
    printf("(New Thread) Looping %d\n", i); 
    sleep(1); 
    } 
} 
+0

한 노트 - pthread_create 함수를 호출하는 PyGILState_Ensure() 및 PyGILState_Release 호출은 중요하지 않은 것처럼 보입니다. 나는 그것이 메인 스레드에 의해 실행되고 있기 때문에 기대되는 것이라고 생각한다. – cursemyziti

답변

3

나는이 될 것이라고 긍정적 아니에요 - receive_audio에서
(새 스레드)는()는 다음과 같이 GIL
(새 스레드) 루핑 0
분할 오류

C 코드를 공개 귀하의 질문과 관련이 있지만, 의심스러운 하나는 모듈 초기화 함수에서 PyEval_ReleaseLock() 호출입니다. 나는 파이썬이 당신의 모듈 이니셜 라이저가 GIL을 그 아래에서 풀어 낼 것으로 기대하고 있으며 어떤 예제 코드 here을 살펴보면이 라인들을 따라 아무것도 보이지 않을 것이라고 생각한다. PyEval_ReleaseLock() 호출을 제거하고 어떤 일이 일어 났는지 알려 주실 수 있습니까?

BTW, 나는 run_thread() 내의 PyGILState _ *() 호출이 아무런 효과가 없어야한다는 데 동의합니다. 당신은 그 (것)들을 다만 제거 할 수 있어야합니다.

+2

니스! 그랬어. 나는 여기에서 코드를 따르고 있었다 : http://www.linuxjournal.com/article/3641?page=0,2 그의 예제는 파이썬을 C 언어로 임베딩하기위한 것이다. 비참한. 감사합니다. – cursemyziti

관련 문제