Error grave de depuración de Python: objeto GC ya rastreado

Mi código de Python se ha estrellado con el error ‘Objeto GC ya rastreado’. Tratando de averiguar el mejor enfoque para depurar esto se bloquea.

OS: Linux.

  • ¿Hay una manera adecuada de depurar este problema.

Hubo un par de sugerencias en el siguiente artículo. Depuración de memoria Python con GDB

No estoy seguro de qué enfoque funcionó para el autor.

  • ¿Hay una manera de generar volcados de memoria en tal escenario que podría ser analizado. Como en el mundo de Windows.

Encontré algún artículo sobre esto. Pero no responde por completo mi pregunta: http://pfigue.github.io/blog/2012/12/28/where-is-my-core-dump-archlinux/

Descubrí la razón de este problema en mi escenario (no necesariamente la única razón para la falla del objeto GC). Utilicé los volcados GDB y Core para depurar este problema.

Tengo código de extensión Python y C (en objeto compartido). El código de Python registra una rutina de callback con el código de C Extension. En un flujo de trabajo determinado, un subproceso del código de Extensión C estaba llamando a la rutina de callback registrada en el código Python.

Esto generalmente funcionó bien, pero cuando varios subprocesos realizaron la misma acción simultáneamente, se produjo el Bloqueo con ‘Objeto GC ya rastreado’.

La sincronización del acceso a los objetos de Python para varios subprocesos resuelve este problema.

Gracias a todos los que respondieron a esto.

Me encontré con este problema usando boost :: python cuando nuestro código C ++ activaría una callback de python. Ocasionalmente obtendría “objeto GC ya rastreado” y el progtwig terminaría.

Pude adjuntar GDB al proceso antes de desencadenar el error. Una cosa interesante, en el código de Python estábamos envolviendo la callback con una función de herramientas, que en realidad estaba ocultando dónde estaba ocurriendo el error real. Después de reemplazar el parcial con una clase envoltura llamable simple. El “error del objeto GC ya rastreado” ya no apareció, en lugar de eso, ahora estaba obteniendo un error de seguridad.

En nuestro boost :: python wrapper, teníamos funciones lambda para manejar una callback de C ++ y la función lambda capturaba la función boost :: python :: object callback. Resultó que, por el motivo que fuera, en el destructor de la lambda, no siempre se adquiría correctamente el GIL al destruir el objeto boost :: python :: que estaba causando la falla de seguridad.

La solución fue no usar una función lambda, sino crear un funtor que se asegure de adquirir el GIL en el destructor antes de llamar a PyDECREF () en el objeto 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 guard(_mutex); PyGILState_STATE state = PyGILState_Ensure(); Py_DECREF(_cb.ptr()); PyGILState_Release(state); _destroyed = true; } void operator ()(topic_ptr topic) { std::lock_guard 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; }; 

El problema es que intenta agregar un objeto dos veces al recolector de basura cíclico de Python.

Echa un vistazo a este error , específicamente:

  • La documentación para apoyar la recolección de basura cíclica en Python
  • Mi parche de documentación para el problema y
  • Mi explicación en el informe de errores en sí

En pocas palabras: si configura Py_TPFLAGS_HAVE_GC y está usando la asignación de memoria incorporada de Python ( tp_alloc estándar / tp_free ), nunca tendrá que llamar manualmente a PyObject_GC_Track() o PyObject_GC_UnTrack() . Python lo maneja todo detrás de tu espalda.

Desafortunadamente, esto no está bien documentado, por el momento. Una vez que haya solucionado el problema, siéntase libre de incluir el informe de error (vinculado arriba) sobre la mejor documentación de este comportamiento.