mirror of https://github.com/grpc/grpc.git
parent
f5691a5fec
commit
16ad9b8280
8 changed files with 273 additions and 14 deletions
@ -0,0 +1,115 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
#include "src/core/lib/iomgr/port.h" |
||||
|
||||
/* This test only relevant on linux systems where epoll() is available */ |
||||
#if defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD) |
||||
#include "src/core/lib/iomgr/ev_epollex_linux.h" |
||||
|
||||
#include <grpc/grpc.h> |
||||
#include <string.h> |
||||
#include <sys/eventfd.h> |
||||
|
||||
#include "test/core/util/test_config.h" |
||||
|
||||
static void pollset_destroy(void* ps, grpc_error* error) { |
||||
grpc_pollset_destroy(static_cast<grpc_pollset*>(ps)); |
||||
gpr_free(ps); |
||||
} |
||||
|
||||
// This test is added to cover the case found in bug:
|
||||
// https://github.com/grpc/grpc/issues/15760
|
||||
static void test_pollable_owner_fd() { |
||||
grpc_core::ExecCtx exec_ctx; |
||||
int ev_fd1; |
||||
int ev_fd2; |
||||
grpc_fd* grpc_fd1; |
||||
grpc_fd* grpc_fd2; |
||||
grpc_pollset* ps; |
||||
gpr_mu* mu; |
||||
|
||||
// == Create two grpc_fds ==
|
||||
// All we need is two file descriptors. Doesn't matter what type. We use
|
||||
// eventfd type here for the purpose of this test
|
||||
ev_fd1 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); |
||||
ev_fd2 = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); |
||||
if (ev_fd1 < 0 || ev_fd2 < 0) { |
||||
gpr_log(GPR_ERROR, "Error in creating event fds for the test"); |
||||
return; |
||||
} |
||||
grpc_fd1 = grpc_fd_create(ev_fd1, "epollex-test-fd1", false); |
||||
grpc_fd2 = grpc_fd_create(ev_fd2, "epollex-test-fd2", false); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// == Create a pollset ==
|
||||
ps = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size())); |
||||
grpc_pollset_init(ps, &mu); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// == Add fd1 to pollset ==
|
||||
grpc_pollset_add_fd(ps, grpc_fd1); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// == Destroy fd1 ==
|
||||
grpc_fd_orphan(grpc_fd1, nullptr, nullptr, "test fd1 orphan"); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// = Add fd2 to pollset ==
|
||||
//
|
||||
// Before https://github.com/grpc/grpc/issues/15760, the following line caused
|
||||
// unexpected behavior (The previous grpc_pollset_add_fd(ps, grpc_fd1) created
|
||||
// an underlying structure in epollex that held a reference to grpc_fd1 which
|
||||
// was being accessed here even after grpc_fd_orphan(grpc_fd1) was called
|
||||
grpc_pollset_add_fd(ps, grpc_fd2); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// == Destroy fd2 ==
|
||||
grpc_fd_orphan(grpc_fd2, nullptr, nullptr, "test fd2 orphan"); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
|
||||
// == Destroy pollset
|
||||
grpc_closure ps_destroy_closure; |
||||
GRPC_CLOSURE_INIT(&ps_destroy_closure, pollset_destroy, ps, |
||||
grpc_schedule_on_exec_ctx); |
||||
grpc_pollset_shutdown(ps, &ps_destroy_closure); |
||||
grpc_core::ExecCtx::Get()->Flush(); |
||||
} |
||||
|
||||
int main(int argc, char** argv) { |
||||
const char* poll_strategy = nullptr; |
||||
grpc_test_init(argc, argv); |
||||
grpc_init(); |
||||
{ |
||||
grpc_core::ExecCtx exec_ctx; |
||||
poll_strategy = grpc_get_poll_strategy_name(); |
||||
if (poll_strategy != nullptr && strcmp(poll_strategy, "epollex") == 0) { |
||||
test_pollable_owner_fd(); |
||||
} else { |
||||
gpr_log(GPR_INFO, |
||||
"Skipping the test. The test is only relevant for 'epollex' " |
||||
"strategy. and the current strategy is: '%s'", |
||||
poll_strategy); |
||||
} |
||||
} |
||||
|
||||
grpc_shutdown(); |
||||
return 0; |
||||
} |
||||
#else /* defined(GRPC_LINUX_EPOLL_CREATE1) && defined(GRPC_LINUX_EVENTFD) */ |
||||
int main(int argc, char** argv) { return 0; } |
||||
#endif |
Loading…
Reference in new issue