示例#1
0
文件: handle.c 项目: myyyy/libguestfs
/* 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;
}
示例#2
0
/* 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;
}
示例#3
0
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);
}