Skip to content

Commit a18463f

Browse files
authored
Support task tracer (#2851)
* Support task tracer * Opt signal trace * Rename BRPC_VALIDATE_GFLAG to BUTIL_VALIDATE_GFLAG * Update picture of document
1 parent 6b29a36 commit a18463f

38 files changed

+1507
-247
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
inputs:
2+
options:
3+
description: extra options for config_brpc.sh
4+
required: false
5+
runs:
6+
using: "composite"
7+
steps:
8+
- run: sudo git clone https://github.com/libunwind/libunwind.git && cd libunwind && sudo git checkout tags/v1.8.1 && sudo mkdir -p /libunwind && sudo autoreconf -i && sudo CC=clang CXX=clang++ ./configure --prefix=/libunwind && sudo make -j ${{env.proc_num}} && sudo make install
9+
shell: bash
10+
- run: sudo apt-get update && sudo apt-get install -y libgtest-dev cmake gdb libstdc++6-9-dbg && cd /usr/src/gtest && sudo cmake . && sudo make -j ${{env.proc_num}} && sudo mv lib/libgtest* /usr/lib/
11+
shell: bash
12+
- run: sh config_brpc.sh --headers="/libunwind/include /usr/include" --libs="/libunwind/lib /usr/lib /usr/lib64" --nodebugsymbols ${{inputs.options}}
13+
shell: bash

.github/actions/install-all-dependences/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ runs:
22
using: "composite"
33
steps:
44
- uses: ./.github/actions/install-essential-dependences
5-
- run: sudo apt-get install -y libgoogle-glog-dev automake bison flex libboost-all-dev libevent-dev libtool pkg-config libibverbs1 libibverbs-dev
5+
- run: sudo apt-get install -y libgoogle-glog-dev automake bison flex libboost-all-dev libevent-dev libtool pkg-config libibverbs1 libibverbs-dev libunwind8-dev
66
shell: bash
77
- run: wget https://archive.apache.org/dist/thrift/0.11.0/thrift-0.11.0.tar.gz && tar -xf thrift-0.11.0.tar.gz
88
shell: bash

.github/workflows/ci-linux.yml

+21-25
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
steps:
3232
- uses: actions/checkout@v2
3333
- uses: ./.github/actions/install-essential-dependences
34-
- name: cmake
34+
- name: cmake
3535
run: |
3636
export CC=gcc && export CXX=g++
3737
mkdir build
@@ -47,7 +47,7 @@ jobs:
4747
steps:
4848
- uses: actions/checkout@v2
4949
- run: bazel test --verbose_failures -- //... -//example/...
50-
50+
5151
gcc-compile-with-boringssl:
5252
runs-on: ubuntu-20.04
5353
steps:
@@ -61,7 +61,7 @@ jobs:
6161
- uses: ./.github/actions/install-all-dependences
6262
- uses: ./.github/actions/init-make-config
6363
with:
64-
options: --cc=gcc --cxx=g++ --with-thrift --with-glog --with-rdma --with-debug-bthread-sche-safety --with-debug-lock
64+
options: --cc=gcc --cxx=g++ --with-thrift --with-glog --with-rdma --with-debug-bthread-sche-safety --with-debug-lock --with-bthread-tracer
6565
- name: compile
6666
run: |
6767
make -j ${{env.proc_num}}
@@ -76,7 +76,7 @@ jobs:
7676
export CC=gcc && export CXX=g++
7777
mkdir build
7878
cd build
79-
cmake -DWITH_MESALINK=OFF -DWITH_GLOG=ON -DWITH_THRIFT=ON -DWITH_RDMA=ON -DWITH_DEBUG_BTHREAD_SCHE_SAFETY=ON -DWITH_DEBUG_LOCK=ON ..
79+
cmake -DWITH_MESALINK=OFF -DWITH_GLOG=ON -DWITH_THRIFT=ON -DWITH_RDMA=ON -DWITH_DEBUG_BTHREAD_SCHE_SAFETY=ON -DWITH_DEBUG_LOCK=ON -WITH_BTHREAD_TRACER=ON ..
8080
- name: compile
8181
run: |
8282
cd build
@@ -105,7 +105,7 @@ jobs:
105105
steps:
106106
- uses: actions/checkout@v2
107107
- uses: ./.github/actions/install-essential-dependences
108-
- name: cmake
108+
- name: cmake
109109
run: |
110110
export CC=clang && export CXX=clang++
111111
mkdir build
@@ -135,7 +135,7 @@ jobs:
135135
- uses: ./.github/actions/install-all-dependences
136136
- uses: ./.github/actions/init-make-config
137137
with:
138-
options: --cc=clang --cxx=clang++ --with-thrift --with-glog --with-rdma --with-debug-bthread-sche-safety --with-debug-lock
138+
options: --cc=clang --cxx=clang++ --with-thrift --with-glog --with-rdma --with-debug-bthread-sche-safety --with-debug-lock --with-bthread-tracer
139139
- name: compile
140140
run: |
141141
make -j ${{env.proc_num}}
@@ -150,7 +150,7 @@ jobs:
150150
export CC=clang && export CXX=clang++
151151
mkdir build
152152
cd build
153-
cmake -DWITH_MESALINK=OFF -DWITH_GLOG=ON -DWITH_THRIFT=ON -DWITH_RDMA=ON -DWITH_DEBUG_BTHREAD_SCHE_SAFETY=ON -DWITH_DEBUG_LOCK=ON ..
153+
cmake -DWITH_MESALINK=OFF -DWITH_GLOG=ON -DWITH_THRIFT=ON -DWITH_RDMA=ON -DWITH_DEBUG_BTHREAD_SCHE_SAFETY=ON -DWITH_DEBUG_LOCK=ON -WITH_BTHREAD_TRACER=ON ..
154154
- name: compile
155155
run: |
156156
cd build
@@ -165,21 +165,17 @@ jobs:
165165
clang-unittest:
166166
runs-on: ubuntu-20.04
167167
steps:
168-
- uses: actions/checkout@v2
169-
- uses: ./.github/actions/install-essential-dependences
170-
- name: install gtest
171-
run: |
172-
sudo apt-get update
173-
sudo apt-get install -y cmake libgtest-dev gdb
174-
cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv lib/libgtest* /usr/lib/
175-
- uses: ./.github/actions/init-make-config
176-
with:
177-
options: --cc=clang --cxx=clang++
178-
- name: compile tests
179-
run: |
180-
cd test
181-
make -j ${{env.proc_num}}
182-
- name: run tests
183-
run: |
184-
cd test
185-
sh ./run_tests.sh
168+
- uses: actions/checkout@v2
169+
- uses: ./.github/actions/install-essential-dependences
170+
- uses: ./.github/actions/init-ut-make-config
171+
with:
172+
options: --cc=clang --cxx=clang++ --with-bthread-tracer
173+
- name: compile tests
174+
run: |
175+
cat config.mk
176+
cd test
177+
make -j ${{env.proc_num}}
178+
- name: run tests
179+
run: |
180+
cd test
181+
sh ./run_tests.sh

CMakeLists.txt

+20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ option(WITH_BORINGSSL "With BoringSSL" OFF)
2424
option(DEBUG "Print debug logs" OFF)
2525
option(WITH_DEBUG_SYMBOLS "With debug symbols" ON)
2626
option(WITH_THRIFT "With thrift framed protocol supported" OFF)
27+
option(WITH_BTHREAD_TRACER "With bthread tracer supported" OFF)
2728
option(WITH_SNAPPY "With snappy" OFF)
2829
option(WITH_RDMA "With RDMA" OFF)
2930
option(WITH_DEBUG_BTHREAD_SCHE_SAFETY "With debugging bthread sche safety" OFF)
@@ -81,6 +82,20 @@ if(WITH_THRIFT)
8182
endif()
8283
endif()
8384

85+
if (WITH_BTHREAD_TRACER)
86+
if (NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux") OR NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64"))
87+
message(FATAL_ERROR "bthread tracer is only supported on Linux x86_64 platform")
88+
endif()
89+
find_path(LIBUNWIND_INCLUDE_PATH NAMES libunwind.h)
90+
find_library(LIBUNWIND_LIB NAMES unwind)
91+
find_library(LIBUNWIND_X86_64_LIB NAMES unwind-x86_64)
92+
if (NOT LIBUNWIND_INCLUDE_PATH OR NOT LIBUNWIND_LIB)
93+
message(FATAL_ERROR "Fail to find libunwind, which is needed by bthread tracer")
94+
endif()
95+
add_definitions(-DBRPC_BTHREAD_TRACER)
96+
include_directories(${LIBUNWIND_INCLUDE_PATH})
97+
endif ()
98+
8499
set(WITH_RDMA_VAL "0")
85100
if(WITH_RDMA)
86101
set(WITH_RDMA_VAL "1")
@@ -319,6 +334,11 @@ if(WITH_SNAPPY)
319334
set(BRPC_PRIVATE_LIBS "${BRPC_PRIVATE_LIBS} -lsnappy")
320335
endif()
321336

337+
if (WITH_BTHREAD_TRACER)
338+
set(DYNAMIC_LIB ${DYNAMIC_LIB} ${LIBUNWIND_LIB} ${LIBUNWIND_X86_64_LIB})
339+
set(BRPC_PRIVATE_LIBS "${BRPC_PRIVATE_LIBS} -lunwind -lunwind-x86_64")
340+
endif()
341+
322342
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
323343
set(DYNAMIC_LIB ${DYNAMIC_LIB} rt)
324344
set(BRPC_PRIVATE_LIBS "${BRPC_PRIVATE_LIBS} -lrt")

README_cn.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
* [bthread or not](docs/cn/bthread_or_not.md)
3939
* [thread-local](docs/cn/thread_local.md)
4040
* [Execution Queue](docs/cn/execution_queue.md)
41+
* [bthread tracer](docs/cn/bthread_tracer.md)
4142
* Client
4243
* [基础功能](docs/cn/client.md)
4344
* [错误码](docs/cn/error_code.md)

config_brpc.sh

+25-4
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ else
3838
LDD=ldd
3939
fi
4040

41-
TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx:,with-glog,with-thrift,with-rdma,with-mesalink,with-debug-bthread-sche-safety,with-debug-lock,nodebugsymbols -n 'config_brpc' -- "$@"`
41+
TEMP=`getopt -o v: --long headers:,libs:,cc:,cxx:,with-glog,with-thrift,with-rdma,with-mesalink,with-bthread-tracer,with-debug-bthread-sche-safety,with-debug-lock,nodebugsymbols -n 'config_brpc' -- "$@"`
4242
WITH_GLOG=0
4343
WITH_THRIFT=0
4444
WITH_RDMA=0
4545
WITH_MESALINK=0
46+
WITH_BTHREAD_TRACER=0
4647
BRPC_DEBUG_BTHREAD_SCHE_SAFETY=0
4748
DEBUGSYMBOLS=-g
4849
BRPC_DEBUG_LOCK=0
@@ -69,6 +70,7 @@ while true; do
6970
--with-thrift) WITH_THRIFT=1; shift 1 ;;
7071
--with-rdma) WITH_RDMA=1; shift 1 ;;
7172
--with-mesalink) WITH_MESALINK=1; shift 1 ;;
73+
--with-bthread-tracer) WITH_BTHREAD_TRACER=1; shift 1 ;;
7274
--with-debug-bthread-sche-safety ) BRPC_DEBUG_BTHREAD_SCHE_SAFETY=1; shift 1 ;;
7375
--with-debug-lock ) BRPC_DEBUG_LOCK=1; shift 1 ;;
7476
--nodebugsymbols ) DEBUGSYMBOLS=; shift 1 ;;
@@ -352,8 +354,27 @@ fi
352354

353355
LEVELDB_HDR=$(find_dir_of_header_or_die leveldb/db.h)
354356

355-
HDRS=$($ECHO "$GFLAGS_HDR\n$PROTOBUF_HDR\n$ABSL_HDR\n$LEVELDB_HDR\n$OPENSSL_HDR" | sort | uniq)
356-
LIBS=$($ECHO "$GFLAGS_LIB\n$PROTOBUF_LIB\n$ABSL_LIB\n$LEVELDB_LIB\n$OPENSSL_LIB\n$SNAPPY_LIB" | sort | uniq)
357+
CPPFLAGS=
358+
359+
if [ $WITH_BTHREAD_TRACER != 0 ]; then
360+
if [ "$SYSTEM" != "Linux" ] || [ "$(uname -m)" != "x86_64" ]; then
361+
>&2 $ECHO "bthread tracer is only supported on Linux x86_64 platform"
362+
exit 1
363+
fi
364+
LIBUNWIND_HDR=$(find_dir_of_header_or_die libunwind.h)
365+
LIBUNWIND_LIB=$(find_dir_of_lib_or_die unwind)
366+
367+
CPPFLAGS="${CPPFLAGS} -DBRPC_BTHREAD_TRACER"
368+
369+
if [ -f "$LIBUNWIND_LIB/libunwind.$SO" ]; then
370+
DYNAMIC_LINKINGS="$DYNAMIC_LINKINGS -lunwind -lunwind-x86_64"
371+
else
372+
STATIC_LINKINGS="$STATIC_LINKINGS -lunwind -lunwind-x86_64"
373+
fi
374+
fi
375+
376+
HDRS=$($ECHO "$LIBUNWIND_HDR\n$GFLAGS_HDR\n$PROTOBUF_HDR\n$ABSL_HDR\n$LEVELDB_HDR\n$OPENSSL_HDR" | sort | uniq)
377+
LIBS=$($ECHO "$LIBUNWIND_LIB\n$GFLAGS_LIB\n$PROTOBUF_LIB\n$ABSL_LIB\n$LEVELDB_LIB\n$OPENSSL_LIB\n$SNAPPY_LIB" | sort | uniq)
357378

358379
absent_in_the_list() {
359380
TMP=`$ECHO "$1\n$2" | sort | uniq`
@@ -411,7 +432,7 @@ append_to_output "STATIC_LINKINGS=$STATIC_LINKINGS"
411432
append_to_output "DYNAMIC_LINKINGS=$DYNAMIC_LINKINGS"
412433

413434
# CPP means C PreProcessing, not C PlusPlus
414-
CPPFLAGS="-DBRPC_WITH_GLOG=$WITH_GLOG -DGFLAGS_NS=$GFLAGS_NS -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=$BRPC_DEBUG_BTHREAD_SCHE_SAFETY -DBRPC_DEBUG_LOCK=$BRPC_DEBUG_LOCK"
435+
CPPFLAGS="${CPPFLAGS} -DBRPC_WITH_GLOG=$WITH_GLOG -DGFLAGS_NS=$GFLAGS_NS -DBRPC_DEBUG_BTHREAD_SCHE_SAFETY=$BRPC_DEBUG_BTHREAD_SCHE_SAFETY -DBRPC_DEBUG_LOCK=$BRPC_DEBUG_LOCK"
415436

416437
# Avoid over-optimizations of TLS variables by GCC>=4.8
417438
# See: https://github.com/apache/brpc/issues/1693

docs/cn/bthread_tracer.md

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
gdb(ptrace)+ gdb_bthread_stack.py主要的缺点是要慢和阻塞进程,需要一种高效的追踪bthread调用栈的方法。
2+
3+
bRPC框架的协作式用户态协程无法像Golang内建的抢占式协程一样实现高效的STW(Stop the World),框架也无法干预用户逻辑的执行,所以要追踪bthread调用栈是比较困难的。
4+
5+
在线追踪bthread调用栈需要解决以下问题:
6+
1. 追踪挂起bthread的调用栈。
7+
2. 追踪运行中bthread的调用栈。
8+
9+
# bthread状态模型
10+
11+
以下是目前的bthread状态模型。
12+
13+
![bthread状态模型](../images/bthread_status_model.svg)
14+
15+
# 设计方案
16+
17+
## 核心思路
18+
19+
为了解决上述两个问题,该方案实现了STB(Stop The Bthread),核心思路可以简单总结为,在追踪bthread调用栈的过程中,状态不能流转到当前追踪方法不支持的状态。STB包含了两种追踪模式:上下文(context)追踪模式和信号追踪模式。
20+
21+
### 上下文(context)追踪模式
22+
上下文追踪模式可以追踪挂起bthread的调用栈。挂起的bthread栈是稳定的,利用TaskMeta.stack中保存的上下文信息(x86_64下关键的寄存器主要是RIP、RSP、RBP),通过一些可以回溯指定上下文调用栈的库来追踪bthread调用栈。但是挂起的bthread随时可能会被唤醒,执行逻辑(包括jump_stack),则bthread栈会一直变化。不稳定的上下文是不能用来追踪调用栈的,需要在jump_stack前拦截bthread的调度,等到调用栈追踪完成后才继续运行bthread。所以,上下文追踪模式支持就绪、挂起这两个状态。
23+
24+
### 信号追踪模式
25+
26+
信号追踪模式可以追踪运行中bthread的调用栈。运行中bthread是不稳定的,不能使用TaskMeta.stack来追踪bthread调用栈。只能另辟蹊径,使用信号中断bthread运行逻辑,在信号处理函数中回溯bthread调用栈。使用信号有两个问题:
27+
28+
1. 异步信号安全问题。
29+
2. 信号追踪模式不支持jump_stack。调用栈回溯需要寄存器信息,但jump_stack会操作寄存器,这个过程是不安全的,所以jump_stack不能被信号中断,需要在jump_stack前拦截bthread的调度,等到bthread调用栈追踪完成后才继续挂起bthread。
30+
31+
所以,追踪模式只支持运行状态。
32+
33+
### 小结
34+
35+
jump_stack是bthread挂起或者运行的必经之路,也是STB的拦截点。STB将状态分成三类:
36+
1. 上下文追踪模式的状态:就绪、挂起。
37+
2. 支持信号追踪模式的状态:运行。
38+
3. 不支持追踪的状态。jump_stack的过程是不允许使用以上两种调用栈追踪方法,需要在jump_stack前拦截bthread的调度,等到调用栈追踪完成后才继续调度bthread。
39+
40+
### 详细流程
41+
42+
以下是引入STB后的bthread状态模型,在原来bthread状态模型的基础上,加入两个状态(拦截点):将运行、挂起中。
43+
44+
![bthread STB状态模型](../images/bthread_stb_model.svg)
45+
46+
经过上述分析,总结出STB的流程:
47+
48+
1. TaskTracer(实现STB的一个模块)收到追踪bthread调用栈的请求时,标识正在追踪。追踪完成后,标识追踪完成,并TaskTracer发信号通知可能处于将运行或者挂起中状态的bthread。根据bthread状态,TaskTracer执行不同的逻辑:
49+
- 创建、就绪但还没分配栈、销毁:直接结束追踪。
50+
- 挂起、就绪:使用上下文追踪模式追踪bthread的调用栈。
51+
- 运行:使用信号追踪模式追踪bthread的调用栈。
52+
- 将运行、挂起中:TaskTracer自旋等到bthread状态流转到下一个状态(挂起或者运行)后继续追踪。
53+
54+
2. TaskTracer追踪时,bthread根据状态也会执行不同的逻辑:
55+
- 创建、就绪但还没分配栈、就绪:不需要额外处理。
56+
- 挂起、运行:通知TaskTracer继续追踪。
57+
- 将运行、挂起中、销毁:bthread通过条件变量等到TaskTracer追踪完成。TaskTracer追踪完成后会通过条件变量通知bthread继续执行jump_stack。
58+
59+
# 使用方法
60+
61+
1. 下载安装libunwind。
62+
2. 给config_brpc.sh增加`--with-bthread-tracer`选项或者给cmake增加`-DWITH_BTHREAD_TRACER=ON`选项。
63+
3. 访问服务的内置服务:`http://ip:port/bthreads/<bthread_id>?st=1`或者代码里调用`bthread::stack_trace()`函数。
64+
4. 如果希望追踪pthread的调用栈,在对应pthread上调用`bthread::init_for_pthread_stack_trace()`函数获取一个伪bthread_t,然后使用步骤3即可获取pthread调用栈。
65+
66+
下面是追踪bthread调用栈的输出示例:
67+
```shell
68+
#0 0x00007fdbbed500b5 __clock_gettime_2
69+
#1 0x000000000041f2b6 butil::cpuwide_time_ns()
70+
#2 0x000000000041f289 butil::cpuwide_time_us()
71+
#3 0x000000000041f1b9 butil::EveryManyUS::operator bool()
72+
#4 0x0000000000413289 (anonymous namespace)::spin_and_log()
73+
#5 0x00007fdbbfa58dc0 bthread::TaskGroup::task_runner()
74+
```
75+
76+
# 相关flag
77+
78+
- `enable_fast_unwind`:是否启用快速回溯功能,默认为true。大多数情况下,不需要关闭快速回溯功能。除非你关注的调用栈函数名转换失败,显示为`<unknown>`,则可以尝试关闭快速回溯功能,但这会导致性能下降。以包含30帧的调用栈举例,快速回溯基本上在200us以内就可以完成,而关闭快速回溯则需要4ms左右,性能下降了近20倍。
79+
- `signal_trace_timeout_ms`:信号追踪模式的超时时间,默认为50ms。虽然libunwind文档显示回溯功能是异步信号安全的,但是[gpertools社区发现libunwind在某些情况下会死锁](https://github.com/gperftools/gperftools/issues/775),所以TaskTracer会设置了超时时间,超时后会放弃回溯,打破死锁。

docs/cn/getting_started.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ brpc默认**不**链接 [tcmalloc](http://goog-perftools.sourceforge.net/doc/tcm
382382

383383
## glog: 3.3+
384384

385-
brpc实现了一个默认的[日志功能](../../src/butil/logging.h)它和glog冲突。要替换成glog,可以给config_brpc.sh增加*--with-glog*选项或者给cmake增加`-DWITH_GLOG=ON`选项。
385+
brpc实现了一个默认的[日志功能](../../src/butil/logging.h)它和glog冲突。要替换成glog,可以给config_brpc.sh增加`--with-glog`选项或者给cmake增加`-DWITH_GLOG=ON`选项。
386386

387387
## valgrind: 3.8+
388388

@@ -392,6 +392,12 @@ brpc会自动检测valgrind(然后注册bthread的栈)。不支持老版本
392392

393393
无已知问题。
394394

395+
## libunwind: 1.3-1.8.1
396+
397+
bRPC默认****链接 [libunwind](https://github.com/libunwind/libunwind)。用户需要追踪bthread功能则链接libunwind,可以给config_brpc.sh增加`--with-bthread-tracer`选项或者给cmake增加`-DWITH_BTHREAD_TRACER=ON`选项。
398+
399+
建议使用最新版本的libunwind。
400+
395401
# 实例追踪
396402

397403
我们提供了一个程序去帮助你追踪和监控所有brpc实例。 只需要在某处运行 [trackme_server](https://github.com/apache/brpc/tree/master/tools/trackme_server/) 然后再带着 -trackme_server=SERVER参数启动需要被追踪的实例。trackme_server将从实例周期性地收到ping消息然后打印日志。您可以从日志中聚合实例地址,并调用实例的内置服务以获取更多信息。

docs/en/getting_started.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -377,14 +377,20 @@ When you remove tcmalloc, not only remove the linkage with tcmalloc but also the
377377

378378
## glog: 3.3+
379379

380-
brpc implements a default [logging utility](../../src/butil/logging.h) which conflicts with glog. To replace this with glog, add *--with-glog* to config_brpc.sh or add `-DWITH_GLOG=ON` to cmake.
380+
brpc implements a default [logging utility](../../src/butil/logging.h) which conflicts with glog. To replace this with glog, add `--with-glog` to config_brpc.sh or add `-DWITH_GLOG=ON` to cmake.
381381

382382
## valgrind: 3.8+
383383

384384
brpc detects valgrind automatically (and registers stacks of bthread). Older valgrind(say 3.2) is not supported.
385385

386386
## thrift: 0.9.3-0.11.0
387387

388+
## libunwind: 1.3-1.8.1
389+
390+
brpc does **not** link [libunwind](https://github.com/libunwind/libunwind) by default. Users link libunwind on-demand by adding `--with-glog` to config_brpc.sh or adding `-DWITH_GLOG=ON` to cmake.
391+
392+
It is recommended to use the latest possible version of libunwind.
393+
388394
no known issues.
389395

390396
# Track instances

docs/images/bthread_status_model.svg

+3
Loading

docs/images/bthread_stb_model.svg

+3
Loading

src/brpc/builtin/bthreads_service.cpp

+15-3
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
// under the License.
1717

1818

19-
#include <ostream>
19+
#include "bthread/bthread.h"
2020
#include "brpc/closure_guard.h" // ClosureGuard
2121
#include "brpc/controller.h" // Controller
2222
#include "brpc/builtin/common.h"
2323
#include "brpc/builtin/bthreads_service.h"
2424

2525
namespace bthread {
26-
void print_task(std::ostream& os, bthread_t tid);
26+
extern void print_task(std::ostream& os, bthread_t tid);
2727
}
2828

2929

@@ -40,12 +40,24 @@ void BthreadsService::default_method(::google::protobuf::RpcController* cntl_bas
4040
const std::string& constraint = cntl->http_request().unresolved_path();
4141

4242
if (constraint.empty()) {
43+
#ifdef BRPC_BTHREAD_TRACER
44+
os << "Use /bthreads/<bthread_id> or /bthreads/<bthread_id>?st=1 for stack trace";
45+
#else
4346
os << "Use /bthreads/<bthread_id>";
47+
#endif // BRPC_BTHREAD_TRACER
4448
} else {
4549
char* endptr = NULL;
4650
bthread_t tid = strtoull(constraint.c_str(), &endptr, 10);
47-
if (*endptr == '\0' || *endptr == '/') {
51+
if (*endptr == '\0' || *endptr == '/' || *endptr == '?') {
4852
::bthread::print_task(os, tid);
53+
54+
#ifdef BRPC_BTHREAD_TRACER
55+
const std::string* st = cntl->http_request().uri().GetQuery("st");
56+
if (NULL != st && *st == "1") {
57+
os << "\nbthread call stack:\n";
58+
::bthread::stack_trace(os, tid);
59+
}
60+
#endif // BRPC_BTHREAD_TRACER
4961
} else {
5062
cntl->SetFailed(ENOMETHOD, "path=%s is not a bthread id",
5163
constraint.c_str());

0 commit comments

Comments
 (0)