Sto incorporando l'interprete Python in un'applicazione C multithread e sono un po 'confuso su quali API dovrei usare per garantire la sicurezza dei thread.Embedded python nell'applicazione C multithread
Da ciò che ho raccolto, quando si incorpora python, spetta all'embeditore di occuparsi del blocco GIL prima di chiamare qualsiasi altra chiamata API Python C. Questo è fatto con queste funzioni:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
Ma questo da solo non sembra essere sufficiente. Ho ancora arresti anomali casuali poiché non sembra fornire l'esclusione reciproca per le API Python.
Dopo aver letto alcune ulteriori documenti ho anche aggiunto:
PyEval_InitThreads();
subito dopo la chiamata a Py_IsInitialized()
ma è lì che la parte confusa viene. I documenti affermano che questa funzione:
inizializzazione e acquisiscono bloccare l'interprete globale
Questo suggerisce che quando questa funzione restituisce, la GIL dovrebbe essere bloccato e deve essere sbloccato in qualche modo. ma in pratica questo non sembra essere richiesto. Con questa linea sul posto il mio multithread ha funzionato perfettamente e l'esclusione reciproca è stata mantenuta dalle funzioni PyGILState_Ensure/Release
.
Quando ho provato ad aggiungere dopo l'PyEval_ReleaseLock()
l'app bloccata in modo piuttosto rapido in una successiva chiamata a PyImport_ExecCodeModule()
.
Quindi cosa mi manca qui?
Questo è sbagliato e potenzialmente dannoso: 'PyEval_SaveThread' dovrebbe sempre essere in congiunzione con' PyEval_RestoreThread'. Come [spiegato altrove] (http://stackoverflow.com/a/15471525/1600898), non provare a rilasciare il blocco dopo averlo inizializzato; lasciatelo a Python per rilasciarlo come parte del suo normale lavoro. – user4815162342
Non vedo perché è dannoso se metti tutte le chiamate a python in blocchi _Block_ _Allow_. D'altra parte, se non chiami "PyEval_SaveThread();" allora il tuo thread principale bloccherà l'accesso di altri thread a Python. In altre parole 'PyGILState_Ensure()' deadlock. – khkarens
Questa è l'unica cosa che funziona sia per incorporare Python che per chiamare in un modulo di estensione. –