Beispiel #1
0
/* Return true if this thread should poll */
static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker,
                         grpc_pollset_worker **worker_hdl, gpr_timespec *now,
                         gpr_timespec deadline) {
  bool do_poll = true;
  if (worker_hdl != NULL) *worker_hdl = worker;
  worker->initialized_cv = false;
  worker->kicked = false;
  worker->pollset = pollset;
  worker->pollable = pollset->current_pollable;

  if (pollset_is_pollable_fd(pollset, worker->pollable)) {
    REF_BY((grpc_fd *)worker->pollable, 2, "one_poll");
  }

  worker_insert(&pollset->root_worker, PWL_POLLSET, worker);
  if (!worker_insert(&worker->pollable->root_worker, PWL_POLLABLE, worker)) {
    worker->initialized_cv = true;
    gpr_cv_init(&worker->cv);
    if (worker->pollable != &pollset->pollable) {
      gpr_mu_unlock(&pollset->pollable.po.mu);
    }
    if (GRPC_TRACER_ON(grpc_polling_trace) &&
        worker->pollable->root_worker != worker) {
      gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset,
              worker->pollable, worker,
              poll_deadline_to_millis_timeout(deadline, *now));
    }
    while (do_poll && worker->pollable->root_worker != worker) {
      if (gpr_cv_wait(&worker->cv, &worker->pollable->po.mu, deadline)) {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset,
                  worker->pollable, worker);
        }
        do_poll = false;
      } else if (worker->kicked) {
        if (GRPC_TRACER_ON(grpc_polling_trace)) {
          gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset, worker->pollable,
                  worker);
        }
        do_poll = false;
      } else if (GRPC_TRACER_ON(grpc_polling_trace) &&
                 worker->pollable->root_worker != worker) {
        gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset,
                worker->pollable, worker);
      }
    }
    if (worker->pollable != &pollset->pollable) {
      gpr_mu_unlock(&worker->pollable->po.mu);
      gpr_mu_lock(&pollset->pollable.po.mu);
      gpr_mu_lock(&worker->pollable->po.mu);
    }
    *now = gpr_now(now->clock_type);
  }

  return do_poll && pollset->shutdown_closure == NULL &&
         pollset->current_pollable == worker->pollable;
}
Beispiel #2
0
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
                    const char *reason) {
  fd->on_done_closure = on_done;
  shutdown(fd->fd, SHUT_RDWR);
  REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
  gpr_mu_lock(&fd->watcher_mu);
  wake_all_watchers_locked(fd);
  gpr_mu_unlock(&fd->watcher_mu);
  UNREF_BY(fd, 2, reason); /* drop the reference */
}
Beispiel #3
0
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
                    const char *reason) {
  fd->on_done_closure = on_done;
  shutdown(fd->fd, SHUT_RDWR);
  gpr_mu_lock(&fd->mu);
  REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
  if (!has_watchers(fd)) {
    fd->closed = 1;
    close(fd->fd);
    grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
  } else {
    wake_all_watchers_locked(fd);
  }
  gpr_mu_unlock(&fd->mu);
  UNREF_BY(fd, 2, reason); /* drop the reference */
}
Beispiel #4
0
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
                    const char *reason) {
    fd->on_done_closure = on_done;
    shutdown(fd->fd, SHUT_RDWR);
    gpr_mu_lock(&fd->watcher_mu);
    REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
    if (!has_watchers(fd)) {
        fd->closed = 1;
        close(fd->fd);
        if (fd->on_done_closure) {
            grpc_iomgr_add_callback(fd->on_done_closure);
        }
    } else {
        wake_all_watchers_locked(fd);
    }
    gpr_mu_unlock(&fd->watcher_mu);
    UNREF_BY(fd, 2, reason); /* drop the reference */
}
Beispiel #5
0
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
                    int *release_fd, const char *reason) {
  fd->on_done_closure = on_done;
  fd->released = release_fd != NULL;
  if (!fd->released) {
    shutdown(fd->fd, SHUT_RDWR);
  } else {
    *release_fd = fd->fd;
  }
  gpr_mu_lock(&fd->mu);
  REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
  if (!has_watchers(fd)) {
    close_fd_locked(exec_ctx, fd);
  } else {
    wake_all_watchers_locked(fd);
  }
  gpr_mu_unlock(&fd->mu);
  UNREF_BY(fd, 2, reason); /* drop the reference */
}
Beispiel #6
0
/* expects pollsets locked, flag whether fd is locked or not */
static grpc_error *pollset_add_fd_locked(grpc_exec_ctx *exec_ctx,
                                         grpc_pollset *pollset, grpc_fd *fd,
                                         bool fd_locked) {
  static const char *err_desc = "pollset_add_fd";
  grpc_error *error = GRPC_ERROR_NONE;
  if (pollset->current_pollable == &g_empty_pollable) {
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG,
              "PS:%p add fd %p; transition pollable from empty to fd", pollset,
              fd);
    /* empty pollable --> single fd pollable */
    pollset_kick_all(exec_ctx, pollset);
    pollset->current_pollable = &fd->pollable;
    if (!fd_locked) gpr_mu_lock(&fd->pollable.po.mu);
    append_error(&error, fd_become_pollable_locked(fd), err_desc);
    if (!fd_locked) gpr_mu_unlock(&fd->pollable.po.mu);
    REF_BY(fd, 2, "pollset_pollable");
  } else if (pollset->current_pollable == &pollset->pollable) {
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG, "PS:%p add fd %p; already multipolling", pollset, fd);
    append_error(&error, pollable_add_fd(pollset->current_pollable, fd),
                 err_desc);
  } else if (pollset->current_pollable != &fd->pollable) {
    grpc_fd *had_fd = (grpc_fd *)pollset->current_pollable;
    if (GRPC_TRACER_ON(grpc_polling_trace))
      gpr_log(GPR_DEBUG,
              "PS:%p add fd %p; transition pollable from fd %p to multipoller",
              pollset, fd, had_fd);
    pollset_kick_all(exec_ctx, pollset);
    pollset->current_pollable = &pollset->pollable;
    if (append_error(&error, pollable_materialize(&pollset->pollable),
                     err_desc)) {
      pollable_add_fd(&pollset->pollable, had_fd);
      pollable_add_fd(&pollset->pollable, fd);
    }
    GRPC_CLOSURE_SCHED(exec_ctx,
                       GRPC_CLOSURE_CREATE(unref_fd_no_longer_poller, had_fd,
                                           grpc_schedule_on_exec_ctx),
                       GRPC_ERROR_NONE);
  }
  return error;
}
Beispiel #7
0
static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                      grpc_closure *on_done, int *release_fd,
                      const char *reason) {
  bool is_fd_closed = false;
  grpc_error *error = GRPC_ERROR_NONE;

  gpr_mu_lock(&fd->pollable.po.mu);
  gpr_mu_lock(&fd->orphaned_mu);
  fd->on_done_closure = on_done;

  /* If release_fd is not NULL, we should be relinquishing control of the file
     descriptor fd->fd (but we still own the grpc_fd structure). */
  if (release_fd != NULL) {
    *release_fd = fd->fd;
  } else {
    close(fd->fd);
    is_fd_closed = true;
  }

  fd->orphaned = true;

  if (!is_fd_closed) {
    gpr_log(GPR_DEBUG, "TODO: handle fd removal?");
  }

  /* Remove the active status but keep referenced. We want this grpc_fd struct
     to be alive (and not added to freelist) until the end of this function */
  REF_BY(fd, 1, reason);

  GRPC_CLOSURE_SCHED(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error));

  gpr_mu_unlock(&fd->orphaned_mu);
  gpr_mu_unlock(&fd->pollable.po.mu);
  UNREF_BY(exec_ctx, fd, 2, reason); /* Drop the reference */
  GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error));
  GRPC_ERROR_UNREF(error);
}