]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/PyModuleRunner.cc
update sources to v12.2.3
[ceph.git] / ceph / src / mgr / PyModuleRunner.cc
CommitLineData
3efd9988
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2016 John Spray <john.spray@redhat.com>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 */
13
14
15// Python.h comes first because otherwise it clobbers ceph's assert
16#include "Python.h"
17
18#include "common/debug.h"
19#include "mgr/Gil.h"
20
21#include "PyModuleRunner.h"
22
23#define dout_context g_ceph_context
24#define dout_subsys ceph_subsys_mgr
25
26
27std::string handle_pyerror();
28
29PyModuleRunner::~PyModuleRunner()
30{
31 Gil gil(pMyThreadState, true);
32
33 if (pClassInstance) {
34 Py_XDECREF(pClassInstance);
35 pClassInstance = nullptr;
36 }
37
38 Py_DECREF(pClass);
39 pClass = nullptr;
40}
41
42int PyModuleRunner::serve()
43{
44 assert(pClassInstance != nullptr);
45
46 // This method is called from a separate OS thread (i.e. a thread not
47 // created by Python), so tell Gil to wrap this in a new thread state.
48 Gil gil(pMyThreadState, true);
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 {
b32b8144
FG
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 // Peek at the exception for the cluster log, before
61 // dumping the backtrace to log log next.
62 PyObject *ptype, *pvalue, *ptraceback;
63 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
64 assert(ptype);
65 assert(pvalue);
66 PyObject *pvalue_str = PyObject_Str(pvalue);
67 std::string exc_msg = PyString_AsString(pvalue_str);
68 Py_DECREF(pvalue_str);
69 PyErr_Restore(ptype, pvalue, ptraceback);
70
71 clog->error() << "Unhandled exception from module '" << module_name
72 << "' while running on mgr." << g_conf->name.get_id()
73 << ": " << exc_msg;
3efd9988
FG
74 derr << module_name << ".serve:" << dendl;
75 derr << handle_pyerror() << dendl;
76 return -EINVAL;
77 }
78
79 return r;
80}
81
82void PyModuleRunner::shutdown()
83{
84 assert(pClassInstance != nullptr);
85
86 Gil gil(pMyThreadState, true);
87
88 auto pValue = PyObject_CallMethod(pClassInstance,
89 const_cast<char*>("shutdown"), nullptr);
90
91 if (pValue != NULL) {
92 Py_DECREF(pValue);
93 } else {
94 derr << "Failed to invoke shutdown() on " << module_name << dendl;
95 derr << handle_pyerror() << dendl;
96 }
97}
98
99void PyModuleRunner::log(int level, const std::string &record)
100{
101#undef dout_prefix
102#define dout_prefix *_dout << "mgr[" << module_name << "] "
103 dout(level) << record << dendl;
104#undef dout_prefix
105#define dout_prefix *_dout << "mgr " << __func__ << " "
106}
107
108void* PyModuleRunner::PyModuleRunnerThread::entry()
109{
110 // No need to acquire the GIL here; the module does it.
111 dout(4) << "Entering thread for " << mod->get_name() << dendl;
112 mod->serve();
113 return nullptr;
114}