/* guestfs_shutdown calls shutdown_backend with check_for_errors = 1. * guestfs_close calls shutdown_backend with check_for_errors = 0. * * 'check_for_errors' is a hint to the backend about whether we care * about errors or not. In the libvirt case it can be used to * optimize the shutdown for speed when we don't care. */ static int shutdown_backend (guestfs_h *g, int check_for_errors) { int ret = 0; if (g->state == CONFIG) return 0; /* Try to sync if autosync flag is set. */ if (g->autosync && g->state == READY) { if (guestfs_internal_autosync (g) == -1) ret = -1; } /* Shut down the backend. */ if (g->backend_ops->shutdown (g, g->backend_data, check_for_errors) == -1) ret = -1; /* Close sockets. */ if (g->conn) { g->conn->ops->free_connection (g, g->conn); g->conn = NULL; } guestfs_int_free_drives (g); g->state = CONFIG; return ret; }
/* Shutdown the backend. */ int guestfs__shutdown (guestfs_h *g) { int ret = 0; if (g->state == CONFIG) return 0; /* Try to sync if autosync flag is set. */ if (g->autosync && g->state == READY) { if (guestfs_internal_autosync (g) == -1) ret = -1; } /* Close sockets. */ if (g->fd[0] >= 0) close (g->fd[0]); if (g->fd[1] >= 0) close (g->fd[1]); if (g->sock >= 0) close (g->sock); g->fd[0] = -1; g->fd[1] = -1; g->sock = -1; if (g->attach_ops->shutdown (g) == -1) ret = -1; g->state = CONFIG; return ret; }
void guestfs_close (guestfs_h *g) { if (g->state == NO_HANDLE) { /* Not safe to call ANY callbacks here, so ... */ fprintf (stderr, _("guestfs_close: called twice on the same handle\n")); return; } if (g->trace) { const char trace_msg[] = "close"; guestfs___call_callbacks_message (g, GUESTFS_EVENT_TRACE, trace_msg, strlen (trace_msg)); } debug (g, "closing guestfs handle %p (state %d)", g, g->state); /* Try to sync if autosync flag is set. */ if (g->autosync && g->state == READY) guestfs_internal_autosync (g); /* If we are valgrinding the daemon, then we *don't* want to kill * the subprocess because we want the final valgrind messages sent * when we close sockets below. However for normal production use, * killing the subprocess is the right thing to do (in case the * daemon or qemu is not responding). */ #ifndef VALGRIND_DAEMON /* Kill the qemu subprocess. */ if (g->state != CONFIG) guestfs_kill_subprocess (g); #endif /* Run user close callbacks. */ guestfs___call_callbacks_void (g, GUESTFS_EVENT_CLOSE); /* Remove all other registered callbacks. Since we've already * called the close callbacks, we shouldn't call any others. */ free (g->events); g->nr_events = 0; g->events = NULL; guestfs___free_inspect_info (g); guestfs___free_drives (&g->drives); /* Close sockets. */ if (g->fd[0] >= 0) close (g->fd[0]); if (g->fd[1] >= 0) close (g->fd[1]); if (g->sock >= 0) close (g->sock); g->fd[0] = -1; g->fd[1] = -1; g->sock = -1; /* Wait for subprocess(es) to exit. */ if (g->pid > 0) waitpid (g->pid, NULL, 0); if (g->recoverypid > 0) waitpid (g->recoverypid, NULL, 0); /* Remove whole temporary directory. */ guestfs___remove_tmpdir (g->tmpdir); free (g->tmpdir); if (g->cmdline) { size_t i; for (i = 0; i < g->cmdline_size; ++i) free (g->cmdline[i]); free (g->cmdline); } /* Mark the handle as dead before freeing it. */ g->state = NO_HANDLE; gl_lock_lock (handles_lock); if (handles == g) handles = g->next; else { guestfs_h *gg; for (gg = handles; gg->next != g; gg = gg->next) ; gg->next = g->next; } gl_lock_unlock (handles_lock); if (g->pda) hash_free (g->pda); free (g->last_error); free (g->path); free (g->qemu); free (g->append); free (g->qemu_help); free (g->qemu_version); free (g); }