Mi sono imbattuto in questo problema utilizzando boost :: python quando il nostro codice C++ avrebbe attivato un callback python.Occasionalmente ricevo "oggetto GC già tracciato" e il programma termina.
Sono stato in grado di collegare GDB al processo prima di attivare l'errore. Una cosa interessante, nel codice python, stavamo avvolgendo la funzione callback con a functools partial, che in realtà mascherava il punto in cui si verificava l'errore reale. Dopo aver sostituito il partial con una semplice classe wrapper chiamabile. L'errore "Oggetto GC già rintracciato" non è più spuntato, ma ora ottenevo solo un segfault.
Nel nostro involucro boost :: python, abbiamo avuto funzioni lambda per gestire un callback in C++ e la funzione lambda ha acquisito la funzione di callback boost :: python :: object. Si è scoperto, per qualsiasi ragione, nel distruttore per il lambda, non sempre stava acquisendo correttamente il GIL quando distruggeva l'oggetto boost :: python :: che stava causando il segfault.
La correzione era di non utilizzare una funzione lambda, ma invece di creare un functor che si assicurasse di acquisire GIL nel distruttore prima di chiamare PyDECREF() su boost :: python :: object.
class callback_wrapper
{
public:
callback_wrapper(object cb): _cb(cb), _destroyed(false) {
}
callback_wrapper(const callback_wrapper& other) {
_destroyed = other._destroyed;
Py_INCREF(other._cb.ptr());
_cb = other._cb;
}
~callback_wrapper() {
std::lock_guard<std::recursive_mutex> guard(_mutex);
PyGILState_STATE state = PyGILState_Ensure();
Py_DECREF(_cb.ptr());
PyGILState_Release(state);
_destroyed = true;
}
void operator()(topic_ptr topic) {
std::lock_guard<std::recursive_mutex> guard(_mutex);
if(_destroyed) {
return;
}
PyGILState_STATE state = PyGILState_Ensure();
try {
_cb(topic);
}
catch(error_already_set) { PyErr_Print(); }
PyGILState_Release(state);
}
object _cb;
std::recursive_mutex _mutex;
bool _destroyed;
};
Sì, è possibile generare un dump. In realtà il dump viene generato automaticamente in caso di crash (segfault) come descritto nell'articolo che hai citato. Ma puoi forzare l'operazione manualmente, inviando un segnale di processo usando 'kill'. BTW Hai guardato su http://pyrit.wordpress.com/2010/02/18/385/? – user3159253
Una volta impostato il core dump, sai dove viene generato il file dump quando il processo si blocca e se ne va? – Feru
Il dump è memorizzato nella directory di lavoro corrente di un processo. – user3159253