diff mbox series

[v2,3/7] trace-cruncher: Allow for detachable custom objects

Message ID 20210819130827.12327-4-y.karadz@gmail.com (mailing list archive)
State Accepted
Headers show
Series trace-cruncher: Refactor instances and kprobes | expand

Commit Message

Yordan Karadzhov Aug. 19, 2021, 1:08 p.m. UTC
libtracefs distinguishes between freeing the resources managed
by an object and the freeing of object itself. One can take
tracefs_instance_destroy() and tracefs_instance_free() as
example. The user can call tracefs_instance_free() without calling
tracefs_instance_destroy(). In this case no memory will leak, but
the instance will continue to exist after the program exits (will
be 'detached'). Here we add mechanisms that will make possible to
detach object from the ftracepy module.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 src/common.h         | 19 +++++++++++++++++--
 src/ftracepy-utils.c | 20 ++++++++++++++++++++
 src/ftracepy-utils.h |  2 ++
 src/ftracepy.c       | 11 ++++++++---
 4 files changed, 47 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/src/common.h b/src/common.h
index fa64696..b7f6a87 100644
--- a/src/common.h
+++ b/src/common.h
@@ -46,28 +46,40 @@  static inline bool is_set(const char *arg)
 	return !(is_all(arg) || is_no_arg(arg));
 }
 
-static inline void no_free()
+static inline void no_free(void *ptr)
 {
 }
 
 #define NO_FREE		no_free
 
+static inline void no_destroy(void *ptr)
+{
+}
+
+#define NO_DESTROY	no_destroy
+
 #define STR(x) #x
 
 #define MAKE_TYPE_STR(x) STR(trace.x)
 
 #define MAKE_DIC_STR(x) STR(libtrace x object)
 
+typedef struct {
+	PyObject_HEAD
+	bool destroy;
+} PyFtrace_Object_HEAD;
+
 #define C_OBJECT_WRAPPER_DECLARE(c_type, py_type)				\
 	typedef struct {							\
 	PyObject_HEAD								\
+	bool destroy;								\
 	struct c_type *ptrObj;							\
 } py_type;									\
 PyObject *py_type##_New(struct c_type *c_ptr);					\
 bool py_type##TypeInit();							\
 bool py_type##_Check(PyObject *obj);						\
 
-#define  C_OBJECT_WRAPPER(c_type, py_type, ptr_free)				\
+#define  C_OBJECT_WRAPPER(c_type, py_type, obj_destroy, ptr_free)		\
 static PyTypeObject py_type##Type = {						\
 	PyVarObject_HEAD_INIT(NULL, 0) MAKE_TYPE_STR(c_type)			\
 };										\
@@ -76,6 +88,7 @@  PyObject *py_type##_New(struct c_type *c_ptr)					\
 	py_type *newObject;							\
 	newObject = PyObject_New(py_type, &py_type##Type);			\
 	newObject->ptrObj = c_ptr;						\
+	newObject->destroy = true;						\
 	return (PyObject *) newObject;						\
 }										\
 static int py_type##_init(py_type *self, PyObject *args, PyObject *kwargs)	\
@@ -85,6 +98,8 @@  static int py_type##_init(py_type *self, PyObject *args, PyObject *kwargs)	\
 }										\
 static void py_type##_dealloc(py_type *self)					\
 {										\
+	if (self->destroy)							\
+		obj_destroy(self->ptrObj);					\
 	ptr_free(self->ptrObj);							\
 	Py_TYPE(self)->tp_free(self);						\
 }										\
diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c
index 6739db7..197804b 100644
--- a/src/ftracepy-utils.c
+++ b/src/ftracepy-utils.c
@@ -536,6 +536,26 @@  PyObject *PyFtrace_dir(PyObject *self)
 	return PyUnicode_FromString(tracefs_tracing_dir());
 }
 
+PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = {"object", NULL};
+	PyFtrace_Object_HEAD *obj_head;
+	PyObject *py_obj = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args,
+					 kwargs,
+					 "O",
+					 kwlist,
+					 &py_obj)) {
+		return false;
+	}
+
+	obj_head = (PyFtrace_Object_HEAD *)py_obj;
+	obj_head->destroy = false;
+
+	Py_RETURN_NONE;
+}
+
 static char aname_pool[] =
 	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h
index 5d7c19c..514c79b 100644
--- a/src/ftracepy-utils.h
+++ b/src/ftracepy-utils.h
@@ -46,6 +46,8 @@  PyObject *PyTep_get_event(PyTep *self, PyObject *args,
 
 PyObject *PyFtrace_dir(PyObject *self);
 
+PyObject *PyFtrace_detach(PyObject *self, PyObject *args, PyObject *kwargs);
+
 PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args,
 						   PyObject *kwargs);
 
diff --git a/src/ftracepy.c b/src/ftracepy.c
index e3fec7b..2296ec9 100644
--- a/src/ftracepy.c
+++ b/src/ftracepy.c
@@ -25,7 +25,7 @@  static PyMethodDef PyTepRecord_methods[] = {
 	{NULL}
 };
 
-C_OBJECT_WRAPPER(tep_record, PyTepRecord, NO_FREE)
+C_OBJECT_WRAPPER(tep_record, PyTepRecord, NO_DESTROY, NO_FREE)
 
 static PyMethodDef PyTepEvent_methods[] = {
 	{"name",
@@ -55,7 +55,7 @@  static PyMethodDef PyTepEvent_methods[] = {
 	{NULL}
 };
 
-C_OBJECT_WRAPPER(tep_event, PyTepEvent, NO_FREE)
+C_OBJECT_WRAPPER(tep_event, PyTepEvent, NO_DESTROY, NO_FREE)
 
 static PyMethodDef PyTep_methods[] = {
 	{"init_local",
@@ -71,7 +71,7 @@  static PyMethodDef PyTep_methods[] = {
 	{NULL}
 };
 
-C_OBJECT_WRAPPER(tep_handle, PyTep, tep_free)
+C_OBJECT_WRAPPER(tep_handle, PyTep, NO_DESTROY, tep_free)
 
 static PyMethodDef ftracepy_methods[] = {
 	{"dir",
@@ -79,6 +79,11 @@  static PyMethodDef ftracepy_methods[] = {
 	 METH_NOARGS,
 	 "Get the absolute path to the tracefs directory."
 	},
+	{"detach",
+	 (PyCFunction) PyFtrace_detach,
+	 METH_VARARGS | METH_KEYWORDS,
+	 "Detach object from the \'ftracepy\' module."
+	},
 	{"create_instance",
 	 (PyCFunction) PyFtrace_create_instance,
 	 METH_VARARGS | METH_KEYWORDS,