grpcio 1.48.2调用完成后触发断言失败问题求助
gRPC服务器崩溃:ASSERTION FAILED: next_worker->state == KICKED(grpcio 1.48.2)
环境信息
- 使用grpcio 1.48.2版本
- 应用由多台部署在Docker容器的gRPC服务器组成,线程池最大工作线程数为10
问题描述
近期遇到断言错误导致gRPC服务器崩溃,错误信息如下:
[E0218 1000 ev_epoll1_linux.cc:1142] ASSERTION FAILED: next_worker->state == KICKED
该错误发生在某gRPC调用成功执行完成后(已在调用末尾添加日志验证调用成功)。
排查到的源码位置
断言失败发生在pollset_kick函数的第1142行左右,函数代码如下:
static grpc_error_handle pollset_kick(grpc_pollset* pollset, grpc_pollset_worker* specific_worker) { GPR_TIMER_SCOPE("pollset_kick", 0); GRPC_STATS_INC_POLLSET_KICK(); grpc_error_handle ret_err = GRPC_ERROR_NONE; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { std::vector<std::string> log; log.push_back(absl::StrFormat( "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset, specific_worker, static_cast<void*>(g_current_thread_pollset), static_cast<void*>(g_current_thread_worker), pollset->root_worker)); if (pollset->root_worker != nullptr) { log.push_back(absl::StrFormat( " {kick_state=%s next=%p {kick_state=%s}}", kick_state_string(pollset->root_worker->state), pollset->root_worker->next, kick_state_string(pollset->root_worker->next->state))); } if (specific_worker != nullptr) { log.push_back(absl::StrFormat(" worker_kick_state=%s", kick_state_string(specific_worker->state))); } gpr_log(GPR_DEBUG, "%s", absl::StrJoin(log, "").c_str()); } if (specific_worker == nullptr) { if (g_current_thread_pollset != pollset) { grpc_pollset_worker* root_worker = pollset->root_worker; if (root_worker == nullptr) { GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER(); pollset->kicked_without_poller = true; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kicked_without_poller"); } goto done; } grpc_pollset_worker* next_worker = root_worker->next; if (root_worker->state == KICKED) { GRPC_STATS_INC_POLLSET_KICKED_AGAIN(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. already kicked %p", root_worker); } SET_KICK_STATE(root_worker, KICKED); goto done; } else if (next_worker->state == KICKED) { GRPC_STATS_INC_POLLSET_KICKED_AGAIN(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. already kicked %p", next_worker); } SET_KICK_STATE(next_worker, KICKED); goto done; } else if (root_worker == next_worker && // only try and wake up a poller // if there is no next worker root_worker == reinterpret_cast<grpc_pollset_worker*>( gpr_atm_no_barrier_load(&g_active_poller))) { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kicked %p", root_worker); } SET_KICK_STATE(root_worker, KICKED); ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd); goto done; } else if (next_worker->state == UNKICKED) { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kicked %p", next_worker); } GPR_ASSERT(next_worker->initialized_cv); SET_KICK_STATE(next_worker, KICKED); gpr_cv_signal(&next_worker->cv); goto done; } else if (next_worker->state == DESIGNATED_POLLER) { if (root_worker->state != DESIGNATED_POLLER) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log( GPR_INFO, " .. kicked root non-poller %p (initialized_cv=%d) (poller=%p)", root_worker, root_worker->initialized_cv, next_worker); } SET_KICK_STATE(root_worker, KICKED); if (root_worker->initialized_cv) { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV(); gpr_cv_signal(&root_worker->cv); } goto done; } else { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. non-root poller %p (root=%p)", next_worker, root_worker); } SET_KICK_STATE(next_worker, KICKED); ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd); goto done; } } else { GRPC_STATS_INC_POLLSET_KICKED_AGAIN(); GPR_ASSERT(next_worker->state == KICKED); SET_KICK_STATE(next_worker, KICKED); goto done; } } else { GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kicked while waking up"); } goto done; } GPR_UNREACHABLE_CODE(goto done); } if (specific_worker->state == KICKED) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. specific worker already kicked"); } goto done; } else if (g_current_thread_worker == specific_worker) { GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. mark %p kicked", specific_worker); } SET_KICK_STATE(specific_worker, KICKED); goto done; } else if (specific_worker == reinterpret_cast<grpc_pollset_worker*>( gpr_atm_no_barrier_load(&g_active_poller))) { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kick active poller"); } SET_KICK_STATE(specific_worker, KICKED); ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd); goto done; } else if (specific_worker->initialized_cv) { GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kick waiting worker"); } SET_KICK_STATE(specific_worker, KICKED); gpr_cv_signal(&specific_worker->cv); goto done; } else { GRPC_STATS_INC_POLLSET_KICKED_AGAIN(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, " .. kick non-waiting worker"); } SET_KICK_STATE(specific_worker, KICKED); goto done; } done: return ret_err; }
求助内容
目前已无进一步调试思路,无意修改grpcio源码或归咎于库本身,希望了解:
- 该断言失败的原因及可能诱因
- 是否属于grpcio库的问题
- 相关调试建议
内容的提问来源于stack exchange,提问作者Yves Halimi
相关产品推荐
相关产品推荐

