| 38 | } |
| 39 | |
| 40 | int PyModuleRunner::serve() |
| 41 | { |
| 42 | ceph_assert(pClassInstance != nullptr); |
| 43 | |
| 44 | // This method is called from a separate OS thread (i.e. a thread not |
| 45 | // created by Python), so tell Gil to wrap this in a new thread state. |
| 46 | Gil gil(py_module->pMyThreadState, true); |
| 47 | if (py_module->perfcounter) { |
| 48 | py_module->perfcounter->set(py_module->l_pym_alive, 1); |
| 49 | } |
| 50 | auto pValue = PyObject_CallMethod(pClassInstance, |
| 51 | const_cast<char*>("serve"), nullptr); |
| 52 | |
| 53 | int r = 0; |
| 54 | if (pValue != NULL) { |
| 55 | Py_DECREF(pValue); |
| 56 | } else { |
| 57 | // This is not a very informative log message because it's an |
| 58 | // unknown/unexpected exception that we can't say much about. |
| 59 | |
| 60 | |
| 61 | // Get short exception message for the cluster log, before |
| 62 | // dumping the full backtrace to the local log. |
| 63 | std::string exc_msg = peek_pyerror(); |
| 64 | |
| 65 | clog->error() << "Unhandled exception from module '" << get_name() |
| 66 | << "' while running on mgr." << g_conf()->name.get_id() |
| 67 | << ": " << exc_msg; |
| 68 | derr << get_name() << ".serve:" << dendl; |
| 69 | derr << handle_pyerror(true, get_name(), "PyModuleRunner::serve") << dendl; |
| 70 | |
| 71 | py_module->fail(exc_msg); |
| 72 | |
| 73 | return -EINVAL; |
| 74 | } |
| 75 | |
| 76 | if (py_module->perfcounter) { |
| 77 | py_module->perfcounter->set(py_module->l_pym_alive, 0); |
| 78 | } |
| 79 | |
| 80 | return r; |
| 81 | } |
| 82 | |
| 83 | void PyModuleRunner::shutdown() |
| 84 | { |
no test coverage detected