Si tratta di un follow-up a Call Python from C++Calling Py_Finalize() da C
Al di avvio del programma che io chiamo la seguente funzione per inizializzare l'interprete:
void initPython(){
PyEval_InitThreads();
Py_Initialize();
PyEval_ReleaseLock();
}
Ogni thread crea il proprio struttura di dati e acquisisce la serratura con:
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
//call python API, process results
PyGILState_Release(gstate);
Piuttosto semplice, una volta che hai capito la GIL, ma il problema è che ho un segfault quando si chiama Py_Finalize().
void exitPython(){
PyEval_AcquireLock();
Py_Finalize();
}
il riferimento è piuttosto dubbioso sul Py_Finalize() (o forse sto solo leggendo nel modo sbagliato) e non sono sicuro se PyEval_AcquireLock() può acquisire il blocco se ci sono alcuni thread attivi e cosa succede se ci sono thread attivi quando viene chiamato Py_Finalize().
Ad ogni modo, ottengo un segfault anche se sono sicuro che tutti i thread hanno terminato il loro lavoro, ma solo se ne è stato creato almeno uno. Per esempio. chiamare initPython() seguito da exitPython() non crea alcun errore.
ho potuto solo ignorare il problema e spero che il sistema operativo sa quello che fa, ma mi piacerebbe prefere se riuscivo a capire cosa sta succedendo ..
Ho commentato tutto tranne PyGILState_Ensure() e Release() e l'errore si verifica ancora. Se commento anche loro non c'è problema .. – Voo
In quel caso, immagino ci sia qualcosa nella gestione dei thread che non viene eseguita correttamente. Sfortunatamente la pagina dell'API C con tutte le funzioni del thread su di esso è tutt'altro che ovvia su quale di quelle chiamate è necessaria. – Kylotan
Le "chiamate necessarie" la maggior parte del tempo sono "Py_BEGIN_ALLOW_THREADS" e la sua controparte. Quelle sono, a loro volta, macro che usano 'PyEval_SaveThread()' e la sua controparte. Quindi se scrivessi qualcosa come OP, seguirei quell'esempio. – Kevin