lghost1999 commented on issue #3349:
URL: https://github.com/apache/brpc/issues/3349#issuecomment-4766138165
这里通过TaskMeta中的tag去获取对应的taskGroup存在问题,TaskMeta中的tag在bthread创建的时候存在tag设置不正确的情况。当调用
`bthread_start_urgent` 或 `bthread_start_background` 且传入 attr 为 NULL 时,
会创建一个直接在当前worker启动的bthread。运行时已经决定了这个线程属于当前taskGroup,但bthread元数据 TaskMeta
中tag设置的却是 -1,而不是当前taskGroup的tag,具体调用链路如下:
```C++
第一层:bthread.cpp:330-356
int bthread_start_urgent(bthread_t* __restrict tid,
const bthread_attr_t* __restrict attr,
void * (*fn)(void*),
void* __restrict arg) {
bthread::TaskGroup* g =
bthread::BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
if (g) {
// if attribute is null use thread local task group
if (bthread::can_run_thread_local(attr)) {
return bthread::TaskGroup::start_foreground(&g, tid, attr, fn,
arg);
}
}
return bthread::start_from_non_worker(tid, attr, fn, arg);
}
int bthread_start_background(bthread_t* __restrict tid,
const bthread_attr_t* __restrict attr,
void * (*fn)(void*),
void* __restrict arg) {
bthread::TaskGroup* g =
bthread::BAIDU_GET_VOLATILE_THREAD_LOCAL(tls_task_group);
if (g) {
// if attribute is null use thread local task group
if (bthread::can_run_thread_local(attr)) {
return g->start_background<false>(tid, attr, fn, arg);
}
}
return bthread::start_from_non_worker(tid, attr, fn, arg);
}
第二层:bthread.cpp:300-303
//判断这个attr的bthread是否可以在本worker中启动,如果不设置attr或者tag匹配,就在本worker中启动
BUTIL_FORCE_INLINE bool can_run_thread_local(const bthread_attr_t*
__restrict attr) {
return attr == nullptr || attr->tag == tls_task_group->tag() ||
attr->tag == BTHREAD_TAG_INVALID;
}
第三层:task_group.cpp:494-564
int TaskGroup::start_foreground(TaskGroup** pg,
bthread_t* __restrict th,
const bthread_attr_t* __restrict attr,
void * (*fn)(void*),
void* __restrict arg) {
if (__builtin_expect(!fn, 0)) {
return EINVAL;
}
const int64_t start_ns = butil::cpuwide_time_ns();
const bthread_attr_t using_attr = (attr ? *attr : BTHREAD_ATTR_NORMAL);
butil::ResourceId<TaskMeta> slot;
TaskMeta* m = butil::get_resource(&slot);
if (BAIDU_UNLIKELY(NULL == m)) {
return ENOMEM;
}
......
}
task_group.cpp:567-618
int TaskGroup::start_background(bthread_t* __restrict th,
const bthread_attr_t* __restrict attr,
void * (*fn)(void*),
void* __restrict arg) {
if (__builtin_expect(!fn, 0)) {
return EINVAL;
}
const int64_t start_ns = butil::cpuwide_time_ns();
const bthread_attr_t using_attr = (attr ? *attr : BTHREAD_ATTR_NORMAL);
butil::ResourceId<TaskMeta> slot;
TaskMeta* m = butil::get_resource(&slot);
if (BAIDU_UNLIKELY(NULL == m)) {
return ENOMEM;
}
......
}
第四层:types.h 140-141
static const bthread_attr_t BTHREAD_ATTR_NORMAL = {BTHREAD_STACKTYPE_NORMAL,
0, NULL,
BTHREAD_TAG_INVALID, {0}};
types.h 38
static const bthread_tag_t BTHREAD_TAG_INVALID = -1;
```
通过上面方式创建的bthread,在获取其TaskMeta中的tag信息,都会返回-1,在调用choose_one_group会直接abort()
```C++
task_group.cpp:350-359
TaskGroup* TaskControl::choose_one_group(bthread_tag_t tag) {
CHECK(tag >= BTHREAD_TAG_DEFAULT && tag < FLAGS_task_group_ntags) << tag;
auto& groups = tag_group(tag);
const auto ngroup = tag_ngroup(tag).load(butil::memory_order_acquire);
if (ngroup != 0) {
return groups[butil::fast_rand_less_than(ngroup)];
}
CHECK(false) << "Impossible: ngroup is 0";
return NULL;
}
```
需要在将taskMeta的tag设置正确
```C++
task_group.cpp
bthread_attr_t using_attr = (attr ? *attr : BTHREAD_ATTR_NORMAL);
//添加代码
if (using_attr.tag == BTHREAD_TAG_INVALID) {
using_attr.tag = tls_task_group ? tls_task_group->tag() :
BTHREAD_TAG_DEFAULT;
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]