Browse Source

PythonTask: don't crash if repr(owner) errors, deal better with bad owners

rdb 9 years ago
parent
commit
47d1b4e220
1 changed files with 21 additions and 11 deletions
  1. 21 11
      panda/src/event/pythonTask.cxx

+ 21 - 11
panda/src/event/pythonTask.cxx

@@ -214,6 +214,19 @@ get_upon_death() {
 ////////////////////////////////////////////////////////////////////
 void PythonTask::
 set_owner(PyObject *owner) {
+#ifndef NDEBUG
+  if (owner != Py_None) {
+    PyObject *add = PyObject_GetAttrString(owner, "_addTask");
+    PyObject *clear = PyObject_GetAttrString(owner, "_clearTask");
+
+    if (add == NULL || !PyCallable_Check(add) ||
+        clear == NULL || !PyCallable_Check(clear)) {
+      Dtool_Raise_TypeError("owner object should have _addTask and _clearTask methods");
+      return;
+    }
+  }
+#endif
+
   if (_owner != NULL && _owner != Py_None && _state != S_inactive) {
     unregister_from_owner();
   }
@@ -546,10 +559,16 @@ do_python_task() {
   ostringstream strm;
 #if PY_MAJOR_VERSION >= 3
   PyObject *str = PyObject_ASCII(result);
+  if (str == NULL) {
+    str = PyUnicode_FromString("<repr error>");
+  }
   strm
     << *this << " returned " << PyUnicode_AsUTF8(str);
 #else
   PyObject *str = PyObject_Repr(result);
+  if (str == NULL) {
+    str = PyString_FromString("<repr error>");
+  }
   strm
     << *this << " returned " << PyString_AsString(str);
 #endif
@@ -672,18 +691,9 @@ call_owner_method(const char *method_name) {
   if (_owner != Py_None) {
     PyObject *func = PyObject_GetAttrString(_owner, (char *)method_name);
     if (func == (PyObject *)NULL) {
-#if PY_MAJOR_VERSION >= 3
-      PyObject *str = PyObject_ASCII(_owner);
       task_cat.error()
-        << "Owner object " << PyUnicode_AsUTF8(str) << " added to "
-        << *this << " has no method " << method_name << "().\n";
-#else
-      PyObject *str = PyObject_Repr(_owner);
-      task_cat.error()
-        << "Owner object " << PyString_AsString(str) << " added to "
-        << *this << " has no method " << method_name << "().\n";
-#endif
-      Py_DECREF(str);
+        << "Owner object added to " << *this << " has no method "
+        << method_name << "().\n";
 
     } else {
       call_function(func);