gRPC trace.cc 的方法 TraceFlagList::Add(TraceFlag* flag) 使其链接列表

Method TraceFlagList::Add(TraceFlag* flag) of gRPC trace.cc makes its chained list loop to itself

本文关键字:flag 列表 链接 TraceFlag cc trace 方法 Add TraceFlagList gRPC      更新时间:2023-10-16

我正在为 32 位 Atom 硬件集成 gRPC。 gRPC 在 64 位 Ubuntu PC 计算机上交叉编译。交叉编译使用Yocto。gRPC 的 CMakeLists.txt 文件包含在带有 add_subdirectory(( 函数的主项目中,并以静态方式链接。为了测试 gRPC,我使用了 Google 的C++语音示例代码。

完整的项目正确构建,并且可以毫无问题地部署在目标硬件上。当我运行示例程序时,执行卡在文件 trace.cc 的方法 TraceFlagList::Set(const char* name, bool enabled( 中的无限循环中。

为了检查问题,我在每个循环中都用这种方法放了一些 printf((:

bool TraceFlagList::Set(const char* name, bool enabled) {
TraceFlag* t;
if (0 == strcmp(name, "all")) {
for (t = root_tracer_; t; t = t->next_tracer_) {
printf("%s 1 %sn", __func__, t->name_);
t->set_enabled(enabled);
}
} else if (0 == strcmp(name, "list_tracers")) {
LogAllTracers();
} else if (0 == strcmp(name, "refcount")) {
for (t = root_tracer_; t; t = t->next_tracer_) {
printf("%s 2 %sn", __func__, t->name_);
if (strstr(t->name_, "refcount") != nullptr) {
t->set_enabled(enabled);
}
}
} else {
bool found = false;
for (t = root_tracer_; t; t = t->next_tracer_) {
printf("%s 3 %sn", __func__, t->name_);
if (0 == strcmp(name, t->name_)) {
t->set_enabled(enabled);
found = true;
}
}
// check for unknowns, but ignore "", to allow to GRPC_TRACE=
if (!found && 0 != strcmp(name, "")) {
gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name);
return false; /* early return */
}
}
return true;
}

似乎在 TraceFlagList 对象中添加了多次 TraceFlag 指针。下面是添加方法:

void TraceFlagList::Add(TraceFlag* flag) {
flag->next_tracer_ = root_tracer_;
root_tracer_ = flag;
}

要添加的第一个元素的next_tracer_成员指向 null。但是经过几次添加后,使用相同的 TraceFlag 指针再次调用 TraceFlagList::Add((。第一个成员将使其next_tracer_成员指向列表的最后一个元素,使列表循环到自身。

运行可执行文件会在命令行中显示以下行:

...
Set 3 api
Set 3 timer_check
Set 3 timer
Set 3 resource_quota
Set 3 executor
Set 3 bdp_estimator
Set 3 client_idle_filter
Set 3 cares_resolver
Set 3 cares_address_sorting
Set 3 round_robin
Set 3 pick_first
Set 3 xds
Set 3 glb
Set 3 inproc
Set 3 health_check_client
Set 3 secure_endpoint
Set 3 http2_stream_state
Set 3 flowctl
Set 3 http
Set 3 connectivity_state
Set 3 tcp
Set 3 http1
Set 3 handshaker
Set 3 channel
Set 3 subchannel_pool
Set 3 subchannel
Set 3 client_channel_routing
Set 3 client_channel_call
Set 3 tsi
Set 3 plugin_credentials
Set 3 server_channel
Set 3 queue_pluck
Set 3 op_failure
Set 3 compression
Set 3 call_error
Set 3 api
Set 3 timer_check
Set 3 timer
Set 3 resource_quota
Set 3 executor
Set 3 bdp_estimator
Set 3 client_idle_filter
Set 3 cares_resolver
Set 3 cares_address_sorting
^C

我必须用ctrl + c破坏可执行文件才能停止它。我通过首先检查要添加到列表中的元素是否存在来解决此问题:

void TraceFlagList::Add(TraceFlag* flag) {
// Check TraceFlag existence in the list before adding it.
for (const TraceFlag* t = root_tracer_; t != nullptr; t = t->next_tracer_) {
if (t == flag) {
gpr_log(GPR_DEBUG, "t%s", t->name_);
printf("TraceFlag %s already in TraceFlagList. Ignore.n", t->name_);
return;
}
}
flag->next_tracer_ = root_tracer_;
root_tracer_ = flag;
}

但这是一个解决方法:在为 Ubuntu 主机构建和运行原始代码时,不存在无限循环的问题。每个跟踪标志指针仅添加一次。我真的不知道 TraceFlag 在 gRPC 中的用途。

我担心解决方法可能会隐藏真正的问题,这可能会产生意想不到的副作用。有没有人知道这个问题的根源?或者我应该在 gRPC 项目中提出这种解决方法?

问候。

这看起来像 https://github.com/grpc/grpc/issues/20690 gRPC核心使用一些全局变量,如果你以某种方式链接了多个版本的grpC库,全局变量就会损坏。