diff options
author | Richard Jones <rjones@redhat.com> | 2010-06-10 12:38:57 +0100 |
---|---|---|
committer | Richard Jones <rjones@redhat.com> | 2010-06-10 14:30:36 +0100 |
commit | dbfd93b72f99ebdded394541a48177c415db8cbf (patch) | |
tree | 5bfe6e3aa6a8f33ab80d268064799985a5f1249b | |
parent | 91b00dc092be17a309f14fc35f41dbf1e41c4c58 (diff) | |
download | libguestfs-dbfd93b72f99ebdded394541a48177c415db8cbf.tar.gz libguestfs-dbfd93b72f99ebdded394541a48177c415db8cbf.tar.xz libguestfs-dbfd93b72f99ebdded394541a48177c415db8cbf.zip |
Add error callback (RHBZ#602599).
Read the note in the man page before using this feature.
-rwxr-xr-x | src/generator.ml | 29 | ||||
-rw-r--r-- | src/guestfs.c | 14 | ||||
-rw-r--r-- | src/guestfs.h | 2 | ||||
-rw-r--r-- | src/guestfs.pod | 18 |
4 files changed, 58 insertions, 5 deletions
diff --git a/src/generator.ml b/src/generator.ml index 0ffd3c70..cf28978d 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 0e4cb73b..1439361d 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 b43cd8bc..3cff4849 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 0f60c8e5..2fa3aceb 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 |