| 142 | } |
| 143 | |
| 144 | std::optional<std::vector<std::byte>> ActivePyModule::dispatch_remote( |
| 145 | const std::string &method, |
| 146 | std::span<std::byte const> pickled_args, |
| 147 | std::span<std::byte const> pickled_kwargs, |
| 148 | std::string *err) |
| 149 | { |
| 150 | ceph_assert(err != nullptr); |
| 151 | |
| 152 | // deserialize arguments. |
| 153 | |
| 154 | Gil gil(py_module->pMyThreadState, true); |
| 155 | |
| 156 | auto pmodule = py_module->pPickleModule; |
| 157 | auto pickled_args_bytes = py_bytes_from_span(pickled_args); |
| 158 | auto args = PyObject_CallMethodObjArgs( |
| 159 | pmodule, |
| 160 | PyUnicode_FromString("loads"), |
| 161 | pickled_args_bytes, |
| 162 | nullptr); |
| 163 | Py_DECREF(pickled_args_bytes); |
| 164 | if (args == nullptr) { |
| 165 | std::string caller = "ActivePyModule::dispatch_remote "s + method; |
| 166 | *err = handle_pyerror(true, get_name(), caller); |
| 167 | derr << "Failed to deserialize (pickle.loads) args: " << *err << dendl; |
| 168 | return std::nullopt; |
| 169 | } |
| 170 | |
| 171 | auto pickled_kwargs_bytes = py_bytes_from_span(pickled_kwargs); |
| 172 | auto kwargs = PyObject_CallMethodObjArgs( |
| 173 | pmodule, |
| 174 | PyUnicode_FromString("loads"), |
| 175 | pickled_kwargs_bytes, |
| 176 | nullptr); |
| 177 | Py_DECREF(pickled_kwargs_bytes); |
| 178 | if (kwargs == nullptr) { |
| 179 | std::string caller = "ActivePyModule::dispatch_remote "s + method; |
| 180 | *err = handle_pyerror(true, get_name(), caller); |
| 181 | derr << "Failed to deserialize (pickle.loads) kwargs: " << *err << dendl; |
| 182 | |
| 183 | Py_DECREF(args); |
| 184 | return std::nullopt; |
| 185 | } |
| 186 | |
| 187 | // Fire the receiving method |
| 188 | auto boundMethod = PyObject_GetAttrString(pClassInstance, method.c_str()); |
| 189 | |
| 190 | // Caller should have done method_exists check first! |
| 191 | ceph_assert(boundMethod != nullptr); |
| 192 | |
| 193 | dout(20) << "Calling " << py_module->get_name() |
| 194 | << "." << method << "..." << dendl; |
| 195 | |
| 196 | auto ret = PyObject_Call(boundMethod, |
| 197 | args, kwargs); |
| 198 | Py_DECREF(boundMethod); |
| 199 | Py_DECREF(kwargs); |
| 200 | Py_DECREF(args); |
| 201 | if (ret == nullptr) { |
no test coverage detected