PyGILState_Ensure () causando deadlock

Estou escrevendo uma extensão Python em C ++, envolvendo uma biblioteca de terceiros que não controlo. Essa biblioteca cria um encadeamento que o Python não sabe nada e, a partir desse encadeamento, chama um retorno de chamada C ++ que forneço à biblioteca. Quero que esse retorno de chamada chame uma função Python, mas recebo um impasse usando a abordagem que li nos documentos. Aqui está a minha interpretação deles.

void Wrapper::myCallback()
{
   PyGILState_STATE gstate=PyGILState_Ensure();
   PyObject *result=PyObject_CallMethod(_pyObj,"callback",nullptr);
   if (result) Py_DECREF(result);
   PyGILState_Release(gstate);
}

Meu código não faz mais nada relacionado a threads, embora eu tenha tentado várias outras coisas. Baseado emesta, por exemplo, tentei ligarPyEval_InitThreads(), mas não é óbvio onde essa chamada deve ser feita para um ramal. Eu coloquei noPyMODINIT_FUNC. Todas essas tentativas levaram a um impasse, travamentos ou erros fatais misteriosos do Python, por exemplo,PyEval_ReleaseThread: estado de thread incorreto.

Este é no Linux com Python 3.6.1. Alguma idéia de como posso obter esse retorno de chamada "simples" para funcionar?

Provável culpado

Não percebi que em outro encadeamento, a biblioteca estava em um loop de espera / espera aguardando o encadeamento do retorno de chamada. Nogdb, info threads tornou isso aparente. A única solução que posso ver é pular essas chamadas específicas para o retorno de chamada; Não vejo uma maneira de protegê-los, dado o ciclo de ocupado / espera. Nesse caso, isso é aceitável, e isso elimina o impasse.

Além disso, parece que eu também preciso chamarPyEval_InitThreads() antes de nada disso. Em uma extensão C ++, não está claro para onde isso deve ir. Uma das respostas sugeriu fazê-lo indiretamente em Python, criando e excluindo um descartávelthreading.Thread. Isso não parecia consertá-lo, provocando umaErro fatal do Python: take_gil: tstate NULL, o que eu acho que significa que ainda não há GIL. Meu palpite, baseado emesta e a questão a que se refere é quePyEval_InitThreads() faz com que o thread atual se torne o thread principal do GIL. Se essa ligação for feita no segmento descartável de curta duração, talvez seja um problema. Sim, estou apenas adivinhando e gostaria de receber uma explicação de alguém que não precisa.

questionAnswers(3)

yourAnswerToTheQuestion