X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fguestfs.c;h=0c0a37fec8d3fc121767c8effb2f1da9b6240dc4;hp=47af20ad0b4484cd319b21b796166462a9786006;hb=99bd425a0a8fb02c27e0c22b32dafa804773a7b1;hpb=f5d2602bf6d40ecc71a5a17e0be9f480e9a4453a diff --git a/src/guestfs.c b/src/guestfs.c index 47af20a..0c0a37f 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -67,6 +67,8 @@ static void stdout_event (void *data, int watch, int fd, int events); static void sock_read_event (void *data, int watch, int fd, int events); static void sock_write_event (void *data, int watch, int fd, int events); +static void close_handles (void); + static int select_add_handle (guestfs_h *g, int fd, int events, guestfs_handle_event_cb cb, void *data); static int select_remove_handle (guestfs_h *g, int watch); static int select_add_timeout (guestfs_h *g, int interval, guestfs_handle_timeout_cb cb, void *data); @@ -95,6 +97,8 @@ enum state { CONFIG, LAUNCHING, READY, BUSY, NO_HANDLE }; struct guestfs_h { + struct guestfs_h *next; /* Linked list of open handles. */ + /* State: see the state machine diagram in the man page guestfs(3). */ enum state state; @@ -144,6 +148,9 @@ struct guestfs_h int msg_next_serial; }; +static guestfs_h *handles = NULL; +static int atexit_handler_set = 0; + guestfs_h * guestfs_create (void) { @@ -175,6 +182,21 @@ guestfs_create (void) */ g->msg_next_serial = 0x00123400; + /* Link the handles onto a global list. This is the one area + * where the library needs to be made thread-safe. (XXX) + */ + /* acquire mutex (XXX) */ + g->next = handles; + handles = g; + if (!atexit_handler_set) { + atexit (close_handles); + atexit_handler_set = 1; + } + /* release mutex (XXX) */ + + if (g->verbose) + fprintf (stderr, "new guestfs handle %p\n", g); + return g; } @@ -183,6 +205,7 @@ guestfs_close (guestfs_h *g) { int i; char filename[256]; + guestfs_h *gg; if (g->state == NO_HANDLE) { /* Not safe to call 'error' here, so ... */ @@ -190,6 +213,9 @@ guestfs_close (guestfs_h *g) return; } + if (g->verbose) + fprintf (stderr, "closing guestfs handle %p (state %d)\n", g, g->state); + /* Remove any handlers that might be called back before we kill the * subprocess. */ @@ -216,9 +242,26 @@ guestfs_close (guestfs_h *g) /* Mark the handle as dead before freeing it. */ g->state = NO_HANDLE; + /* acquire mutex (XXX) */ + if (handles == g) + handles = g->next; + else { + for (gg = handles; gg->next != g; gg = gg->next) + ; + gg->next = g->next; + } + /* release mutex (XXX) */ + free (g); } +/* Close all open handles (called from atexit(3)). */ +static void +close_handles (void) +{ + while (handles) guestfs_close (handles); +} + static void default_error_cb (guestfs_h *g, void *data, const char *msg) { @@ -531,6 +574,8 @@ guestfs_launch (guestfs_h *g) close (rfd[0]); dup (wfd[0]); dup (rfd[1]); + close (wfd[0]); + close (rfd[1]); #if 0 /* Set up a new process group, so we can signal this process