---
generator/generator | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)
diff --git a/generator/generator b/generator/generator
index f6a4856..9bcb08d 100755
--- a/generator/generator
+++ b/generator/generator
@@ -3982,6 +3982,13 @@ let print_python_closure_wrapper { cbname; cbargs } =
pr " const struct user_data *data = user_data;\n";
pr " int ret = 0;\n";
pr "\n";
+ pr " /* The C callback is always registered, even if there's no
Python\n";
+ pr " * callback. This is because we may need to unregister an\n";
+ pr " * associated persistent buffer.\n";
+ pr " */\n";
+ pr " if (data->fn == NULL)\n";
+ pr " return 0;\n";
+ pr "\n";
pr " PyGILState_STATE py_save = PyGILState_UNLOCKED;\n";
pr " PyObject *py_args, *py_ret;\n";
List.iter (
@@ -4253,10 +4260,24 @@ let print_python_binding name { args; optargs; ret; may_set_error
} =
pr " }\n";
pr " }\n";
pr " else\n";
- pr " %s.callback = NULL; /* we're not going to call it */\n"
cbname
+ pr " %s_user_data->fn = NULL;\n" cbname
| OFlags (n, _) -> pr " %s_u32 = %s;\n" n n
) optargs;
+ (* If there is a BytesPersistIn/Out parameter then we need to
+ * increment the refcount and save the pointer into
+ * completion_callback.user_data so we can decrement the
+ * refcount on command completion.
+ *)
+ List.iter (
+ function
+ | BytesPersistIn (n, _) | BytesPersistOut (n, _) ->
+ pr " /* Increment refcount since buffer may be saved by libnbd. */\n";
+ pr " Py_INCREF (%s);\n" n;
+ pr " completion_user_data->buf = %s;\n" n;
+ | _ -> ()
+ ) args;
+
(* Call the underlying C function. *)
pr " ret = nbd_%s (h" name;
List.iter (
@@ -4384,7 +4405,8 @@ let generate_python_methods_c () =
pr " * and freed in the free_user_data function below.\n";
pr " */\n";
pr "struct user_data {\n";
- pr " PyObject *fn; /* Pointer to Python function. */\n";
+ pr " PyObject *fn; /* Optional pointer to Python function. */\n";
+ pr " PyObject *buf; /* Optional pointer to persistent buffer. */\n";
pr "};\n";
pr "\n";
pr "static struct user_data *\n";
@@ -4403,7 +4425,10 @@ let generate_python_methods_c () =
pr "{\n";
pr " struct user_data *data = user_data;\n";
pr "\n";
- pr " Py_DECREF (data->fn);\n";
+ pr " if (data->fn != NULL)\n";
+ pr " Py_DECREF (data->fn);\n";
+ pr " if (data->buf != NULL)\n";
+ pr " Py_DECREF (data->buf);\n";
pr " free (data);\n";
pr "}\n";
pr "\n";
--
2.22.0