|
|
|
@ -143,6 +143,7 @@ struct grpc_fd { |
|
|
|
|
/* Indicates that the fd is shutdown and that any pending read/write closures
|
|
|
|
|
should fail */ |
|
|
|
|
bool shutdown; |
|
|
|
|
grpc_error *shutdown_error; /* reason for shutdown: set iff shutdown==true */ |
|
|
|
|
|
|
|
|
|
/* The fd is either closed or we relinquished control of it. In either cases,
|
|
|
|
|
this indicates that the 'fd' on this structure is no longer valid */ |
|
|
|
@ -907,6 +908,7 @@ static void unref_by(grpc_fd *fd, int n) { |
|
|
|
|
fd->freelist_next = fd_freelist; |
|
|
|
|
fd_freelist = fd; |
|
|
|
|
grpc_iomgr_unregister_object(&fd->iomgr_object); |
|
|
|
|
if (fd->shutdown) GRPC_ERROR_UNREF(fd->shutdown_error); |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&fd_freelist_mu); |
|
|
|
|
} else { |
|
|
|
@ -1058,11 +1060,11 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
GRPC_ERROR_UNREF(error); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static grpc_error *fd_shutdown_error(bool shutdown) { |
|
|
|
|
if (!shutdown) { |
|
|
|
|
static grpc_error *fd_shutdown_error(grpc_fd *fd) { |
|
|
|
|
if (!fd->shutdown) { |
|
|
|
|
return GRPC_ERROR_NONE; |
|
|
|
|
} else { |
|
|
|
|
return GRPC_ERROR_CREATE("FD shutdown"); |
|
|
|
|
return GRPC_ERROR_CREATE_REFERENCING("FD shutdown", &fd->shutdown_error, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1076,7 +1078,7 @@ static void notify_on_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
} else if (*st == CLOSURE_READY) { |
|
|
|
|
/* already ready ==> queue the closure to run immediately */ |
|
|
|
|
*st = CLOSURE_NOT_READY; |
|
|
|
|
grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd->shutdown)); |
|
|
|
|
grpc_closure_sched(exec_ctx, closure, fd_shutdown_error(fd)); |
|
|
|
|
} else { |
|
|
|
|
/* upcallptr was set to a different closure. This is an error! */ |
|
|
|
|
gpr_log(GPR_ERROR, |
|
|
|
@ -1098,7 +1100,7 @@ static int set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd, |
|
|
|
|
return 0; |
|
|
|
|
} else { |
|
|
|
|
/* waiting ==> queue closure */ |
|
|
|
|
grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd->shutdown)); |
|
|
|
|
grpc_closure_sched(exec_ctx, *st, fd_shutdown_error(fd)); |
|
|
|
|
*st = CLOSURE_NOT_READY; |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
@ -1123,17 +1125,20 @@ static bool fd_is_shutdown(grpc_fd *fd) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Might be called multiple times */ |
|
|
|
|
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { |
|
|
|
|
static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { |
|
|
|
|
gpr_mu_lock(&fd->po.mu); |
|
|
|
|
/* Do the actual shutdown only once */ |
|
|
|
|
if (!fd->shutdown) { |
|
|
|
|
fd->shutdown = true; |
|
|
|
|
fd->shutdown_error = why; |
|
|
|
|
|
|
|
|
|
shutdown(fd->fd, SHUT_RDWR); |
|
|
|
|
/* Flush any pending read and write closures. Since fd->shutdown is 'true'
|
|
|
|
|
at this point, the closures would be called with 'success = false' */ |
|
|
|
|
set_ready_locked(exec_ctx, fd, &fd->read_closure); |
|
|
|
|
set_ready_locked(exec_ctx, fd, &fd->write_closure); |
|
|
|
|
} else { |
|
|
|
|
GRPC_ERROR_UNREF(why); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&fd->po.mu); |
|
|
|
|
} |
|
|
|
|