[Libguestfs] [PATCH v2] Add error callback (RHBZ#602599).
Richard W.M. Jones
rjones at redhat.com
Thu Jun 10 12:30:09 UTC 2010
Slightly updated version of this patch. Firstly this updates the
linker script so you can actually use this new call. Secondly it adds
a test.
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
New in Fedora 11: Fedora Windows cross-compiler. Compile Windows
programs, test, and build Windows installers. Over 70 libraries supprt'd
http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw
-------------- next part --------------
>From 7221e107070ed2f7b26c7ae8bc9a3c2a917ea7d4 Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at redhat.com>
Date: Thu, 10 Jun 2010 12:38:57 +0100
Subject: [PATCH] Add error callback (RHBZ#602599).
Read the note in the man page before using this feature.
---
src/generator.ml | 29 ++++++++++++++++++++++++-----
src/guestfs.c | 14 ++++++++++++++
src/guestfs.h | 2 ++
src/guestfs.pod | 18 ++++++++++++++++++
4 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/src/generator.ml b/src/generator.ml
index f5e7474..7cb678e 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -6337,6 +6337,7 @@ and generate_linker_script () =
"guestfs_get_error_handler";
"guestfs_get_out_of_memory_handler";
"guestfs_last_error";
+ "guestfs_set_close_callback";
"guestfs_set_error_handler";
"guestfs_set_launch_done_callback";
"guestfs_set_log_message_callback";
@@ -6885,6 +6886,13 @@ is_available (const char *group)
return r == 0;
}
+static void
+incr (guestfs_h *g, void *iv)
+{
+ int *i = (int *) iv;
+ (*i)++;
+}
+
";
(* Generate a list of commands which are not tested anywhere. *)
@@ -7066,11 +7074,22 @@ int main (int argc, char *argv[])
) test_names;
pr "\n";
- pr " guestfs_close (g);\n";
- pr " unlink (\"test1.img\");\n";
- pr " unlink (\"test2.img\");\n";
- pr " unlink (\"test3.img\");\n";
- pr "\n";
+ pr " /* Check close callback is called. */
+ int close_sentinel = 1;
+ guestfs_set_close_callback (g, incr, &close_sentinel);
+
+ guestfs_close (g);
+
+ if (close_sentinel != 2) {
+ fprintf (stderr, \"close callback was not called\\n\");
+ exit (EXIT_FAILURE);
+ }
+
+ unlink (\"test1.img\");
+ unlink (\"test2.img\");
+ unlink (\"test3.img\");
+
+";
pr " if (n_failed > 0) {\n";
pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
diff --git a/src/guestfs.c b/src/guestfs.c
index 0e4cb73..1439361 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -183,6 +183,8 @@ struct guestfs_h
void * subprocess_quit_cb_data;
guestfs_launch_done_cb launch_done_cb;
void * launch_done_cb_data;
+ guestfs_close_cb close_cb;
+ void * close_cb_data;
int msg_next_serial;
};
@@ -294,6 +296,10 @@ guestfs_close (guestfs_h *g)
if (g->verbose)
fprintf (stderr, "closing guestfs handle %p (state %d)\n", g, g->state);
+ /* Run user close callback before anything else. */
+ if (g->close_cb)
+ g->close_cb (g, g->close_cb_data);
+
/* Try to sync if autosync flag is set. */
if (g->autosync && g->state == READY) {
guestfs_umount_all (g);
@@ -1927,6 +1933,14 @@ guestfs_set_launch_done_callback (guestfs_h *g,
g->launch_done_cb_data = opaque;
}
+void
+guestfs_set_close_callback (guestfs_h *g,
+ guestfs_close_cb cb, void *opaque)
+{
+ g->close_cb = cb;
+ g->close_cb_data = opaque;
+}
+
/*----------------------------------------------------------------------*/
/* This is the code used to send and receive RPC messages and (for
diff --git a/src/guestfs.h b/src/guestfs.h
index b43cd8b..3cff484 100644
--- a/src/guestfs.h
+++ b/src/guestfs.h
@@ -56,10 +56,12 @@ extern guestfs_abort_cb guestfs_get_out_of_memory_handler (guestfs_h *g);
typedef void (*guestfs_log_message_cb) (guestfs_h *g, void *data, char *buf, int len);
typedef void (*guestfs_subprocess_quit_cb) (guestfs_h *g, void *data);
typedef void (*guestfs_launch_done_cb) (guestfs_h *g, void *data);
+typedef void (*guestfs_close_cb) (guestfs_h *g, void *data);
extern void guestfs_set_log_message_callback (guestfs_h *g, guestfs_log_message_cb cb, void *opaque);
extern void guestfs_set_subprocess_quit_callback (guestfs_h *g, guestfs_subprocess_quit_cb cb, void *opaque);
extern void guestfs_set_launch_done_callback (guestfs_h *g, guestfs_launch_done_cb cb, void *opaque);
+extern void guestfs_set_close_callback (guestfs_h *g, guestfs_close_cb cb, void *opaque);
/*--- Structures and actions ---*/
#include <stdint.h>
diff --git a/src/guestfs.pod b/src/guestfs.pod
index 0f60c8e..2fa3ace 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -1042,6 +1042,24 @@ The callback function C<cb> will be called when the child process
becomes ready first time after it has been launched. (This
corresponds to a transition from LAUNCHING to the READY state).
+=head2 guestfs_set_close_callback
+
+ typedef void (*guestfs_close_cb) (guestfs_h *g, void *opaque);
+ void guestfs_set_close_callback (guestfs_h *g,
+ guestfs_close_cb cb,
+ void *opaque);
+
+The callback function C<cb> will be called while the handle
+is being closed (synchronously from L</guestfs_close>).
+
+Note that libguestfs installs an L<atexit(3)> handler to try to
+clean up handles that are open when the program exits. This
+means that this callback might be called indirectly from
+L<exit(3)>, which can cause unexpected problems in higher-level
+languages (eg. if your HLL interpreter has already been cleaned
+up by the time this is called, and if your callback then jumps
+into some HLL function).
+
=head1 BLOCK DEVICE NAMING
In the kernel there is now quite a profusion of schemata for naming
--
1.6.6.1
More information about the Libguestfs
mailing list