Wpadłem na ten problem używając boost :: python, gdy nasz kod C++ wyzwalałby wywołanie Pythona.Od czasu do czasu dostaję "obiekt GC już wyśledzony" i program się zakończy.
Udało mi się dołączyć GDB do procesu przed wyzwoleniem błędu. Jedną z interesujących rzeczy w kodzie Pythona było zawijanie wywołania zwrotnego z częściowym functools, który faktycznie maskował miejsce wystąpienia prawdziwego błędu. Po zastąpieniu częściowej prostą klasą wrappera. "Obiekt GC już wykrył błąd" już nie pojawił się, zamiast tego właśnie dostałem właśnie segfault.
W naszym dopalaczu :: python, mieliśmy funkcje lambda do obsługi wywołania zwrotnego C++, a funkcja lambda przechwyciła funkcję wywołania funkcji :: :: wywołania funkcji :: python. Z jakiegoś powodu okazało się, że w destruktorze dla lambda nie zawsze poprawnie pozyskiwał GILa podczas niszczenia obiektu boost :: python ::, który powodował uszkodzenie.
Poprawka polegała na tym, aby nie używać funkcji lambda, ale zamiast tego utworzyć funktor, który upewnia się, że GIL zostanie użyty w destruktorze przed wywołaniem PyDECREF() na obiekcie boost :: python ::.
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;
};
Tak, możliwe jest wygenerowanie zrzutu. Właściwie zrzut jest generowany automatycznie po awarii (segfault), jak opisano w artykule, o którym wspomniałeś. Ale możesz wymusić operację ręcznie, wysyłając sygnał procesu za pomocą 'kill'. BTW Czy obejrzałeś http://pyrit.wordpress.com/2010/02/18/385/? – user3159253
Po skonfigurowaniu zrzutu pamięci, czy wiesz, gdzie generowany jest plik zrzutu, gdy proces się zawiesza i znika? – Feru
Zrzut jest przechowywany w bieżącym katalogu roboczym procesu. – user3159253