From 43a78030b146d5e680efe984f8e1561f5cbfd168 Mon Sep 17 00:00:00 2001 From: Dan Born Date: Tue, 5 Jan 2016 17:17:45 -0800 Subject: [PATCH 1/3] Expose the fd in grpc_fd and grpc_tcp. Fixes a bug where grpc_fd::released was not initialized. --- src/core/iomgr/fd_posix.c | 9 +++++++++ src/core/iomgr/fd_posix.h | 3 +++ src/core/iomgr/tcp_posix.c | 6 ++++++ src/core/iomgr/tcp_posix.h | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/src/core/iomgr/fd_posix.c b/src/core/iomgr/fd_posix.c index 00710d83bdf..4ca4714e8d4 100644 --- a/src/core/iomgr/fd_posix.c +++ b/src/core/iomgr/fd_posix.c @@ -101,6 +101,7 @@ static grpc_fd *alloc_fd(int fd) { r->read_watcher = r->write_watcher = NULL; r->on_done_closure = NULL; r->closed = 0; + r->released = 0; return r; } @@ -210,6 +211,14 @@ static int has_watchers(grpc_fd *fd) { fd->inactive_watcher_root.next != &fd->inactive_watcher_root; } +int grpc_fd_wrapped_fd(grpc_fd *fd) { + if (fd->released || fd->closed) { + return -1; + } else { + return fd->fd; + } +} + 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; diff --git a/src/core/iomgr/fd_posix.h b/src/core/iomgr/fd_posix.h index df4eb64d4c9..4cec739df1e 100644 --- a/src/core/iomgr/fd_posix.h +++ b/src/core/iomgr/fd_posix.h @@ -105,6 +105,9 @@ struct grpc_fd { This takes ownership of closing fd. */ grpc_fd *grpc_fd_create(int fd, const char *name); +/* Return the wrapped fd, or -1 if it has been released or closed. */ +int grpc_fd_wrapped_fd(grpc_fd *fd); + /* Releases fd to be asynchronously destroyed. on_done is called when the underlying file descriptor is definitely close()d. If on_done is NULL, no callback will be made. diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index f3be41aa571..65783a7afaa 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -473,6 +473,12 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, return &tcp->base; } +int grpc_tcp_fd(grpc_endpoint *ep) { + grpc_tcp *tcp = (grpc_tcp *)ep; + GPR_ASSERT(ep->vtable == &vtable); + return grpc_fd_wrapped_fd(tcp->em_fd); +} + void grpc_tcp_destroy_and_release_fd(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, int *fd, grpc_closure *done) { grpc_tcp *tcp = (grpc_tcp *)ep; diff --git a/src/core/iomgr/tcp_posix.h b/src/core/iomgr/tcp_posix.h index b554983ae1a..495ed009c8d 100644 --- a/src/core/iomgr/tcp_posix.h +++ b/src/core/iomgr/tcp_posix.h @@ -56,6 +56,12 @@ extern int grpc_tcp_trace; grpc_endpoint *grpc_tcp_create(grpc_fd *fd, size_t read_slice_size, const char *peer_string); +/* Return the tcp endpoint's fd, or -1 if this is not available. Does not + release the fd. + Requires: ep must be a tcp endpoint. + */ +int grpc_tcp_fd(grpc_endpoint *ep); + /* Destroy the tcp endpoint without closing its fd. *fd will be set and done * will be called when the endpoint is destroyed. * Requires: ep must be a tcp endpoint and fd must not be NULL. */ From 76d21f9b10dd252bd5fbd7083c1036c2489aed74 Mon Sep 17 00:00:00 2001 From: Dan Born Date: Wed, 6 Jan 2016 20:38:47 -0800 Subject: [PATCH 2/3] Unit tests for new functions --- test/core/iomgr/tcp_posix_test.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 9feac931a37..183cec2a015 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -389,7 +389,8 @@ void on_fd_released(grpc_exec_ctx *exec_ctx, void *arg, int success) { grpc_pollset_kick(&g_pollset, NULL); } -/* Do a read_test, then release fd and try to read/write again. */ +/* Do a read_test, then release fd and try to read/write again. Verify that + grpc_tcp_fd() is available before the fd is released. */ static void release_fd_test(size_t num_bytes, size_t slice_size) { int sv[2]; grpc_endpoint *ep; @@ -408,6 +409,7 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) { create_sockets(sv); ep = grpc_tcp_create(grpc_fd_create(sv[1], "read_test"), slice_size, "test"); + GPR_ASSERT(grpc_tcp_fd(ep) == sv[1] && sv[1] >= 0); grpc_endpoint_add_to_pollset(&exec_ctx, ep, &g_pollset); written_bytes = fill_socket_partial(sv[0], num_bytes); @@ -435,6 +437,7 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) { gpr_slice_buffer_destroy(&state.incoming); grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb); + GPR_ASSERT(grpc_tcp_fd(ep) < 0); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (!fd_released_done) { grpc_pollset_worker worker; @@ -443,6 +446,7 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) { } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); GPR_ASSERT(fd_released_done == 1); + GPR_ASSERT(grpc_tcp_fd(ep) < 0); GPR_ASSERT(fd == sv[1]); grpc_exec_ctx_finish(&exec_ctx); From a7ed54cba76c9c2cf39876e0a2b52fb78c15adb0 Mon Sep 17 00:00:00 2001 From: Dan Born Date: Thu, 7 Jan 2016 12:48:37 -0800 Subject: [PATCH 3/3] Don't use ep after destroy in the test. --- test/core/iomgr/tcp_posix_test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 183cec2a015..f8ba8d901f7 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -437,7 +437,6 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) { gpr_slice_buffer_destroy(&state.incoming); grpc_tcp_destroy_and_release_fd(&exec_ctx, ep, &fd, &fd_released_cb); - GPR_ASSERT(grpc_tcp_fd(ep) < 0); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (!fd_released_done) { grpc_pollset_worker worker; @@ -446,7 +445,6 @@ static void release_fd_test(size_t num_bytes, size_t slice_size) { } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); GPR_ASSERT(fd_released_done == 1); - GPR_ASSERT(grpc_tcp_fd(ep) < 0); GPR_ASSERT(fd == sv[1]); grpc_exec_ctx_finish(&exec_ctx);