| 273 | } |
| 274 | |
| 275 | PyObject *CPythonHandler::Callback( |
| 276 | HANDLER_TYPE typ, |
| 277 | const char *format /* = NULL */, |
| 278 | ... |
| 279 | ) |
| 280 | { |
| 281 | va_list va; |
| 282 | PyObject *args; |
| 283 | PyObject *ret = NULL; |
| 284 | |
| 285 | if (format && *format) { |
| 286 | va_start(va, format); |
| 287 | args = Py_VaBuildValue((char *)format, va); |
| 288 | va_end(va); |
| 289 | } |
| 290 | else |
| 291 | args = PyTuple_New(0); |
| 292 | |
| 293 | if (args == NULL) |
| 294 | return NULL; |
| 295 | |
| 296 | if (!PyTuple_Check(args)) { |
| 297 | PyObject *a; |
| 298 | |
| 299 | a = PyTuple_New(1); |
| 300 | if (a == NULL) |
| 301 | goto done; |
| 302 | if (PyTuple_SET_ITEM(a, 0, args) < 0) { |
| 303 | Py_DECREF(a); |
| 304 | goto done; |
| 305 | } |
| 306 | // 'args' ref consumed by _SET_ITEM. |
| 307 | args = a; |
| 308 | } |
| 309 | |
| 310 | ret = DoCallback(typ, args); |
| 311 | if (!ret) { |
| 312 | if (m_engine->m_reload_exception && |
| 313 | PyErr_ExceptionMatches(m_engine->m_reload_exception)) { |
| 314 | PyErr_Clear(); |
| 315 | // Need to call term first |
| 316 | PyObject *temp_args = Py_BuildValue("(i)", 0); |
| 317 | ret = DoCallback(HANDLER_TERM, temp_args); |
| 318 | Py_XDECREF(temp_args); |
| 319 | if (!ret) { |
| 320 | ExtensionError(NULL, "Terminating for reload failed"); |
| 321 | PyErr_Clear(); |
| 322 | } |
| 323 | Py_XDECREF(ret); |
| 324 | // Now force the reload and refresh of all callbacks. |
| 325 | if (!LoadHandler(true)) |
| 326 | goto done; |
| 327 | Py_XDECREF(m_callback_init); |
| 328 | m_callback_init = NULL; |
| 329 | Py_XDECREF(m_callback_do); |
| 330 | m_callback_do = NULL; |
| 331 | Py_XDECREF(m_callback_term); |
| 332 | m_callback_term = NULL; |
no test coverage detected