| 849 | |
| 850 | |
| 851 | static PyObject * |
| 852 | ceph_dispatch_remote(BaseMgrModule *self, PyObject *args) |
| 853 | { |
| 854 | // PyArgs_ParseTuple doesn't give us refcounts here |
| 855 | char *other_module = nullptr; |
| 856 | char *method = nullptr; |
| 857 | PyObject *remote_args = nullptr; |
| 858 | PyObject *remote_kwargs = nullptr; |
| 859 | if (!PyArg_ParseTuple(args, "ssOO:ceph_dispatch_remote", |
| 860 | &other_module, &method, &remote_args, &remote_kwargs)) { |
| 861 | return nullptr; |
| 862 | } |
| 863 | |
| 864 | // Early error handling, because if the module doesn't exist then we |
| 865 | // won't be able to use its thread state to set python error state |
| 866 | // inside dispatch_remote(). |
| 867 | if (!self->py_modules->module_exists(other_module)) { |
| 868 | derr << "no module '" << other_module << "'" << dendl; |
| 869 | PyErr_SetString(PyExc_ImportError, "Module not found"); |
| 870 | return nullptr; |
| 871 | } |
| 872 | |
| 873 | auto pmodule = self->this_module->py_module->pPickleModule; |
| 874 | auto pickled_args = PyObject_CallMethodObjArgs( |
| 875 | pmodule, |
| 876 | PyUnicode_FromString("dumps"), |
| 877 | remote_args, |
| 878 | nullptr); |
| 879 | if (pickled_args == nullptr) { |
| 880 | std::string caller = "ceph_dispatch_remote "s + " " + method; |
| 881 | std::string err = handle_pyerror(true, other_module, caller); |
| 882 | PyErr_SetString(PyExc_RuntimeError, err.c_str()); |
| 883 | derr << err << dendl; |
| 884 | return nullptr; |
| 885 | } |
| 886 | std::span<std::byte const> pickled_args_span = py_bytes_as_span(pickled_args); |
| 887 | |
| 888 | auto pickled_kwargs = PyObject_CallMethodObjArgs( |
| 889 | pmodule, |
| 890 | PyUnicode_FromString("dumps"), |
| 891 | remote_kwargs, |
| 892 | nullptr); |
| 893 | if (pickled_kwargs == nullptr) { |
| 894 | std::string caller = "ceph_dispatch_remote "s + " " + method; |
| 895 | std::string err = handle_pyerror(true, other_module, caller); |
| 896 | PyErr_SetString(PyExc_RuntimeError, err.c_str()); |
| 897 | derr << err << dendl; |
| 898 | |
| 899 | Py_DECREF(pickled_args); |
| 900 | return nullptr; |
| 901 | } |
| 902 | std::span<std::byte const> pickled_kwargs_span = |
| 903 | py_bytes_as_span(pickled_kwargs); |
| 904 | |
| 905 | // Drop GIL from calling python thread state, it will be taken |
| 906 | // both for checking for method existence and for executing method. |
| 907 | PyThreadState *tstate = PyEval_SaveThread(); |
| 908 |
nothing calls this directly
no test coverage detected