Blob Blame History Raw
From 17a912a449fa75b5c12ac3acab596b476699c671 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 3 Aug 2021 14:19:38 +0100
Subject: [PATCH] python: Implement .cleanup() method

(cherry picked from commit f2fe99e4b0f54467ab8028eaf2d039cf918b2961)
---
 plugins/python/nbdkit-python-plugin.pod | 20 +++++++++++++++++---
 plugins/python/plugin.c                 | 19 +++++++++++++++++++
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod
index 6f5f2c00..a92a557f 100644
--- a/plugins/python/nbdkit-python-plugin.pod
+++ b/plugins/python/nbdkit-python-plugin.pod
@@ -257,6 +257,12 @@ There are no arguments or return value.
 
 There are no arguments or return value.
 
+=item C<cleanup>
+
+(Optional, nbdkit E<ge> 1.28)
+
+There are no arguments or return value.
+
 =item C<list_exports>
 
 (Optional)
@@ -498,10 +504,18 @@ optionally using C<nbdkit.set_error> first.
 
 =over 4
 
-=item Missing: C<load> and C<unload>
+=item Missing: C<load>
 
-These are not needed because you can just use ordinary Python
-constructs.
+This is not needed since you can use regular Python mechanisms like
+top level statements to run code when the module is loaded.
+
+=item Missing: C<unload>
+
+This is missing, but in nbdkit E<ge> 1.28 you can put code in the
+C<cleanup()> function to have it run when nbdkit exits.  In earlier
+versions of nbdkit, using a Python
+L<atexit|https://docs.python.org/3/library/atexit.html> handler is
+recommended.
 
 =item Missing:
 C<name>,
diff --git a/plugins/python/plugin.c b/plugins/python/plugin.c
index 64430a1a..f85512b4 100644
--- a/plugins/python/plugin.c
+++ b/plugins/python/plugin.c
@@ -298,6 +298,24 @@ py_after_fork (void)
   return 0;
 }
 
+static void
+py_cleanup (void)
+{
+  ACQUIRE_PYTHON_GIL_FOR_CURRENT_SCOPE;
+  PyObject *fn;
+  PyObject *r;
+
+  if (callback_defined ("cleanup", &fn)) {
+    PyErr_Clear ();
+
+    r = PyObject_CallObject (fn, NULL);
+    Py_DECREF (fn);
+    if (check_python_failure ("cleanup") == -1)
+      return;
+    Py_DECREF (r);
+  }
+}
+
 static int
 py_list_exports (int readonly, int is_tls, struct nbdkit_exports *exports)
 {
@@ -1039,6 +1057,7 @@ static struct nbdkit_plugin plugin = {
   .thread_model       = py_thread_model,
   .get_ready          = py_get_ready,
   .after_fork         = py_after_fork,
+  .cleanup            = py_cleanup,
   .list_exports       = py_list_exports,
   .default_export     = py_default_export,
 
-- 
2.31.1