Fix a race that could cause a double delete

pull/2726/head
Craig Tiller 9 years ago
parent e2b3bfa4e4
commit 0613e5835b
  1. 6
      src/core/iomgr/fd_posix.c
  2. 1
      src/core/iomgr/fd_posix.h
  3. 2
      src/core/iomgr/tcp_server_posix.c

@ -102,6 +102,7 @@ static grpc_fd *alloc_fd(int fd) {
r->freelist_next = NULL; r->freelist_next = NULL;
r->read_watcher = r->write_watcher = NULL; r->read_watcher = r->write_watcher = NULL;
r->on_done_closure = NULL; r->on_done_closure = NULL;
r->closed = 0;
return r; return r;
} }
@ -209,6 +210,8 @@ void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
REF_BY(fd, 1, reason); /* remove active status, but keep referenced */ REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
gpr_mu_lock(&fd->watcher_mu); gpr_mu_lock(&fd->watcher_mu);
if (!has_watchers(fd)) { if (!has_watchers(fd)) {
GPR_ASSERT(!fd->closed);
fd->closed = 1;
close(fd->fd); close(fd->fd);
if (fd->on_done_closure) { if (fd->on_done_closure) {
grpc_iomgr_add_callback(fd->on_done_closure); grpc_iomgr_add_callback(fd->on_done_closure);
@ -426,7 +429,8 @@ void grpc_fd_end_poll(grpc_fd_watcher *watcher, int got_read, int got_write) {
if (kick) { if (kick) {
maybe_wake_one_watcher_locked(fd); maybe_wake_one_watcher_locked(fd);
} }
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd)) { if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
fd->closed = 1;
close(fd->fd); close(fd->fd);
if (fd->on_done_closure != NULL) { if (fd->on_done_closure != NULL) {
grpc_iomgr_add_callback(fd->on_done_closure); grpc_iomgr_add_callback(fd->on_done_closure);

@ -60,6 +60,7 @@ struct grpc_fd {
gpr_mu set_state_mu; gpr_mu set_state_mu;
gpr_atm shutdown; gpr_atm shutdown;
int closed;
/* The watcher list. /* The watcher list.

@ -142,6 +142,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
static void finish_shutdown(grpc_tcp_server *s) { static void finish_shutdown(grpc_tcp_server *s) {
s->shutdown_complete(s->shutdown_complete_arg); s->shutdown_complete(s->shutdown_complete_arg);
s->shutdown_complete = NULL;
gpr_mu_destroy(&s->mu); gpr_mu_destroy(&s->mu);
@ -157,6 +158,7 @@ static void destroyed_port(void *server, int success) {
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
finish_shutdown(s); finish_shutdown(s);
} else { } else {
GPR_ASSERT(s->destroyed_ports < s->nports);
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
} }
} }

Loading…
Cancel
Save