diff --git a/BUILD b/BUILD
index d07546280d3..9aff85c753b 100644
--- a/BUILD
+++ b/BUILD
@@ -529,6 +529,7 @@ grpc_cc_library(
"src/core/lib/gpr/tmpfile_windows.cc",
"src/core/lib/gpr/wrap_memcpy.cc",
"src/core/lib/gprpp/arena.cc",
+ "src/core/lib/gprpp/examine_stack.cc",
"src/core/lib/gprpp/fork.cc",
"src/core/lib/gprpp/global_config_env.cc",
"src/core/lib/gprpp/host_port.cc",
@@ -558,6 +559,7 @@ grpc_cc_library(
"src/core/lib/gpr/useful.h",
"src/core/lib/gprpp/arena.h",
"src/core/lib/gprpp/atomic.h",
+ "src/core/lib/gprpp/examine_stack.h",
"src/core/lib/gprpp/fork.h",
"src/core/lib/gprpp/global_config.h",
"src/core/lib/gprpp/global_config_custom.h",
@@ -581,6 +583,7 @@ grpc_cc_library(
"absl/strings:str_format",
"absl/synchronization",
"absl/time:time",
+ "absl/types:optional",
],
language = "c++",
public_hdrs = GPR_PUBLIC_HDRS,
diff --git a/BUILD.gn b/BUILD.gn
index 0c0f30d5654..d530100358c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -147,6 +147,8 @@ config("grpc_config") {
"src/core/lib/gprpp/arena.cc",
"src/core/lib/gprpp/arena.h",
"src/core/lib/gprpp/atomic.h",
+ "src/core/lib/gprpp/examine_stack.cc",
+ "src/core/lib/gprpp/examine_stack.h",
"src/core/lib/gprpp/fork.cc",
"src/core/lib/gprpp/fork.h",
"src/core/lib/gprpp/global_config.h",
@@ -173,6 +175,7 @@ config("grpc_config") {
"src/core/lib/profiling/timers.h",
]
deps = [
+ ":absl/types:optional",
":absl/time:time",
":absl/synchronization:synchronization",
":absl/strings:strings",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8f1e9e2f82..b69c00befa7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -819,6 +819,9 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx error_details_test)
add_dependencies(buildtests_cxx evaluate_args_test)
add_dependencies(buildtests_cxx eventmanager_libuv_test)
+ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+ add_dependencies(buildtests_cxx examine_stack_test)
+ endif()
add_dependencies(buildtests_cxx exception_test)
add_dependencies(buildtests_cxx filter_end2end_test)
add_dependencies(buildtests_cxx flaky_network_test)
@@ -897,6 +900,9 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx settings_timeout_test)
add_dependencies(buildtests_cxx shutdown_test)
add_dependencies(buildtests_cxx simple_request_bad_client_test)
+ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+ add_dependencies(buildtests_cxx stack_tracer_test)
+ endif()
add_dependencies(buildtests_cxx stat_test)
add_dependencies(buildtests_cxx static_metadata_test)
add_dependencies(buildtests_cxx stats_test)
@@ -1310,6 +1316,7 @@ add_library(gpr
src/core/lib/gpr/tmpfile_windows.cc
src/core/lib/gpr/wrap_memcpy.cc
src/core/lib/gprpp/arena.cc
+ src/core/lib/gprpp/examine_stack.cc
src/core/lib/gprpp/fork.cc
src/core/lib/gprpp/global_config_env.cc
src/core/lib/gprpp/host_port.cc
@@ -1352,6 +1359,7 @@ target_include_directories(gpr
)
target_link_libraries(gpr
${_gRPC_ALLTARGETS_LIBRARIES}
+ absl::optional
absl::time
absl::synchronization
absl::strings
@@ -2086,7 +2094,6 @@ add_library(grpc_test_util
test/core/util/cmdline.cc
test/core/util/debugger_macros.cc
test/core/util/eval_args_mock_endpoint.cc
- test/core/util/examine_stack.cc
test/core/util/fuzzer_util.cc
test/core/util/grpc_profiler.cc
test/core/util/histogram.cc
@@ -2100,6 +2107,7 @@ add_library(grpc_test_util
test/core/util/reconnect_server.cc
test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc
+ test/core/util/stack_tracer.cc
test/core/util/subprocess_posix.cc
test/core/util/subprocess_windows.cc
test/core/util/test_config.cc
@@ -2158,7 +2166,6 @@ add_library(grpc_test_util_unsecure
test/core/util/cmdline.cc
test/core/util/debugger_macros.cc
test/core/util/eval_args_mock_endpoint.cc
- test/core/util/examine_stack.cc
test/core/util/fuzzer_util.cc
test/core/util/grpc_profiler.cc
test/core/util/histogram.cc
@@ -2172,6 +2179,7 @@ add_library(grpc_test_util_unsecure
test/core/util/reconnect_server.cc
test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc
+ test/core/util/stack_tracer.cc
test/core/util/subprocess_posix.cc
test/core/util/subprocess_windows.cc
test/core/util/test_config.cc
@@ -10980,6 +10988,49 @@ target_link_libraries(eventmanager_libuv_test
)
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+ add_executable(examine_stack_test
+ test/core/gprpp/examine_stack_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+ )
+
+ target_include_directories(examine_stack_test
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ ${_gRPC_RE2_INCLUDE_DIR}
+ ${_gRPC_SSL_INCLUDE_DIR}
+ ${_gRPC_UPB_GENERATED_DIR}
+ ${_gRPC_UPB_GRPC_GENERATED_DIR}
+ ${_gRPC_UPB_INCLUDE_DIR}
+ ${_gRPC_ZLIB_INCLUDE_DIR}
+ third_party/googletest/googletest/include
+ third_party/googletest/googletest
+ third_party/googletest/googlemock/include
+ third_party/googletest/googlemock
+ ${_gRPC_PROTO_GENS_DIR}
+ )
+
+ target_link_libraries(examine_stack_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr
+ address_sorting
+ upb
+ absl::symbolize
+ absl::stacktrace
+ ${_gRPC_GFLAGS_LIBRARIES}
+ )
+
+
+endif()
endif()
if(gRPC_BUILD_TESTS)
@@ -14249,6 +14300,48 @@ target_link_libraries(simple_request_bad_client_test
)
+endif()
+if(gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+ add_executable(stack_tracer_test
+ test/core/util/stack_tracer_test.cc
+ third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
+ )
+
+ target_include_directories(stack_tracer_test
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+ ${_gRPC_RE2_INCLUDE_DIR}
+ ${_gRPC_SSL_INCLUDE_DIR}
+ ${_gRPC_UPB_GENERATED_DIR}
+ ${_gRPC_UPB_GRPC_GENERATED_DIR}
+ ${_gRPC_UPB_INCLUDE_DIR}
+ ${_gRPC_ZLIB_INCLUDE_DIR}
+ third_party/googletest/googletest/include
+ third_party/googletest/googletest
+ third_party/googletest/googlemock/include
+ third_party/googletest/googlemock
+ ${_gRPC_PROTO_GENS_DIR}
+ )
+
+ target_link_libraries(stack_tracer_test
+ ${_gRPC_PROTOBUF_LIBRARIES}
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ grpc_test_util
+ grpc
+ gpr
+ address_sorting
+ upb
+ absl::symbolize
+ ${_gRPC_GFLAGS_LIBRARIES}
+ )
+
+
+endif()
endif()
if(gRPC_BUILD_TESTS)
@@ -15155,7 +15248,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/cmdline.cc
test/core/util/debugger_macros.cc
test/core/util/eval_args_mock_endpoint.cc
- test/core/util/examine_stack.cc
test/core/util/fuzzer_util.cc
test/core/util/grpc_profiler.cc
test/core/util/histogram.cc
@@ -15169,6 +15261,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
test/core/util/reconnect_server.cc
test/core/util/resolve_localhost_ip46.cc
test/core/util/slice_splitter.cc
+ test/core/util/stack_tracer.cc
test/core/util/subprocess_posix.cc
test/core/util/subprocess_windows.cc
test/core/util/test_config.cc
@@ -16189,7 +16282,7 @@ generate_pkgconfig(
"gRPC platform support library"
"${gRPC_CORE_VERSION}"
""
- "-lgpr -labsl_status -labsl_cord -labsl_str_format_internal -labsl_bad_optional_access -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity"
+ "-lgpr -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity"
""
"gpr.pc")
@@ -16199,7 +16292,7 @@ generate_pkgconfig(
"high performance general RPC framework"
"${gRPC_CORE_VERSION}"
"gpr openssl"
- "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_bad_variant_access -labsl_city -labsl_status -labsl_cord -labsl_str_format_internal -labsl_bad_optional_access -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity"
+ "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_bad_variant_access -labsl_city -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity"
""
"grpc.pc")
@@ -16209,7 +16302,7 @@ generate_pkgconfig(
"high performance general RPC framework without SSL"
"${gRPC_CORE_VERSION}"
"gpr"
- "-lgrpc_unsecure -labsl_status -labsl_cord -labsl_str_format_internal -labsl_bad_optional_access -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity"
+ "-lgrpc_unsecure -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity"
""
"grpc_unsecure.pc")
@@ -16219,7 +16312,7 @@ generate_pkgconfig(
"C++ wrapper for gRPC"
"${gRPC_CPP_VERSION}"
"grpc"
- "-lgrpc++ -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_bad_variant_access -labsl_city -labsl_status -labsl_cord -labsl_str_format_internal -labsl_bad_optional_access -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity"
+ "-lgrpc++ -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_bad_variant_access -labsl_city -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity"
""
"grpc++.pc")
@@ -16229,6 +16322,6 @@ generate_pkgconfig(
"C++ wrapper for gRPC without SSL"
"${gRPC_CPP_VERSION}"
"grpc_unsecure"
- "-lgrpc++_unsecure -labsl_status -labsl_cord -labsl_str_format_internal -labsl_bad_optional_access -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_raw_logging_internal -labsl_log_severity"
+ "-lgrpc++_unsecure -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity"
""
"grpc++_unsecure.pc")
diff --git a/Makefile b/Makefile
index 94f8cc39489..0782f7d94e8 100644
--- a/Makefile
+++ b/Makefile
@@ -1742,6 +1742,7 @@ LIBGPR_SRC = \
src/core/lib/gpr/tmpfile_windows.cc \
src/core/lib/gpr/wrap_memcpy.cc \
src/core/lib/gprpp/arena.cc \
+ src/core/lib/gprpp/examine_stack.cc \
src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/global_config_env.cc \
src/core/lib/gprpp/host_port.cc \
diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml
index f73e9b9cb4a..df6bdeed97b 100644
--- a/build_autogenerated.yaml
+++ b/build_autogenerated.yaml
@@ -295,6 +295,7 @@ libs:
- src/core/lib/gpr/useful.h
- src/core/lib/gprpp/arena.h
- src/core/lib/gprpp/atomic.h
+ - src/core/lib/gprpp/examine_stack.h
- src/core/lib/gprpp/fork.h
- src/core/lib/gprpp/global_config.h
- src/core/lib/gprpp/global_config_custom.h
@@ -343,6 +344,7 @@ libs:
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
- src/core/lib/gprpp/arena.cc
+ - src/core/lib/gprpp/examine_stack.cc
- src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/global_config_env.cc
- src/core/lib/gprpp/host_port.cc
@@ -354,6 +356,7 @@ libs:
- src/core/lib/profiling/basic_timers.cc
- src/core/lib/profiling/stap_timers.cc
deps:
+ - absl/types:optional
- absl/time:time
- absl/synchronization:synchronization
- absl/strings:strings
@@ -1415,7 +1418,6 @@ libs:
- test/core/util/cmdline.h
- test/core/util/debugger_macros.h
- test/core/util/eval_args_mock_endpoint.h
- - test/core/util/examine_stack.h
- test/core/util/fuzzer_util.h
- test/core/util/grpc_profiler.h
- test/core/util/histogram.h
@@ -1428,6 +1430,7 @@ libs:
- test/core/util/reconnect_server.h
- test/core/util/resolve_localhost_ip46.h
- test/core/util/slice_splitter.h
+ - test/core/util/stack_tracer.h
- test/core/util/subprocess.h
- test/core/util/test_config.h
- test/core/util/test_tcp_server.h
@@ -1437,7 +1440,6 @@ libs:
- test/core/util/cmdline.cc
- test/core/util/debugger_macros.cc
- test/core/util/eval_args_mock_endpoint.cc
- - test/core/util/examine_stack.cc
- test/core/util/fuzzer_util.cc
- test/core/util/grpc_profiler.cc
- test/core/util/histogram.cc
@@ -1451,6 +1453,7 @@ libs:
- test/core/util/reconnect_server.cc
- test/core/util/resolve_localhost_ip46.cc
- test/core/util/slice_splitter.cc
+ - test/core/util/stack_tracer.cc
- test/core/util/subprocess_posix.cc
- test/core/util/subprocess_windows.cc
- test/core/util/test_config.cc
@@ -1473,7 +1476,6 @@ libs:
- test/core/util/cmdline.h
- test/core/util/debugger_macros.h
- test/core/util/eval_args_mock_endpoint.h
- - test/core/util/examine_stack.h
- test/core/util/fuzzer_util.h
- test/core/util/grpc_profiler.h
- test/core/util/histogram.h
@@ -1486,6 +1488,7 @@ libs:
- test/core/util/reconnect_server.h
- test/core/util/resolve_localhost_ip46.h
- test/core/util/slice_splitter.h
+ - test/core/util/stack_tracer.h
- test/core/util/subprocess.h
- test/core/util/test_config.h
- test/core/util/test_tcp_server.h
@@ -1495,7 +1498,6 @@ libs:
- test/core/util/cmdline.cc
- test/core/util/debugger_macros.cc
- test/core/util/eval_args_mock_endpoint.cc
- - test/core/util/examine_stack.cc
- test/core/util/fuzzer_util.cc
- test/core/util/grpc_profiler.cc
- test/core/util/histogram.cc
@@ -1509,6 +1511,7 @@ libs:
- test/core/util/reconnect_server.cc
- test/core/util/resolve_localhost_ip46.cc
- test/core/util/slice_splitter.cc
+ - test/core/util/stack_tracer.cc
- test/core/util/subprocess_posix.cc
- test/core/util/subprocess_windows.cc
- test/core/util/test_config.cc
@@ -5928,6 +5931,26 @@ targets:
- address_sorting
- upb
uses_polling: false
+- name: examine_stack_test
+ gtest: true
+ build: test
+ language: c++
+ headers: []
+ src:
+ - test/core/gprpp/examine_stack_test.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr
+ - address_sorting
+ - upb
+ - absl/debugging:symbolize
+ - absl/debugging:stacktrace
+ platforms:
+ - linux
+ - posix
+ - mac
+ uses_polling: false
- name: exception_test
gtest: true
build: test
@@ -7335,6 +7358,25 @@ targets:
corpus_dirs:
- test/core/security/corpus/ssl_server_corpus
maxlen: 2048
+- name: stack_tracer_test
+ gtest: true
+ build: test
+ language: c++
+ headers: []
+ src:
+ - test/core/util/stack_tracer_test.cc
+ deps:
+ - grpc_test_util
+ - grpc
+ - gpr
+ - address_sorting
+ - upb
+ - absl/debugging:symbolize
+ platforms:
+ - linux
+ - posix
+ - mac
+ uses_polling: false
- name: stat_test
gtest: true
build: test
@@ -7701,7 +7743,6 @@ targets:
- test/core/util/cmdline.h
- test/core/util/debugger_macros.h
- test/core/util/eval_args_mock_endpoint.h
- - test/core/util/examine_stack.h
- test/core/util/fuzzer_util.h
- test/core/util/grpc_profiler.h
- test/core/util/histogram.h
@@ -7714,6 +7755,7 @@ targets:
- test/core/util/reconnect_server.h
- test/core/util/resolve_localhost_ip46.h
- test/core/util/slice_splitter.h
+ - test/core/util/stack_tracer.h
- test/core/util/subprocess.h
- test/core/util/test_config.h
- test/core/util/test_tcp_server.h
@@ -7726,7 +7768,6 @@ targets:
- test/core/util/cmdline.cc
- test/core/util/debugger_macros.cc
- test/core/util/eval_args_mock_endpoint.cc
- - test/core/util/examine_stack.cc
- test/core/util/fuzzer_util.cc
- test/core/util/grpc_profiler.cc
- test/core/util/histogram.cc
@@ -7740,6 +7781,7 @@ targets:
- test/core/util/reconnect_server.cc
- test/core/util/resolve_localhost_ip46.cc
- test/core/util/slice_splitter.cc
+ - test/core/util/stack_tracer.cc
- test/core/util/subprocess_posix.cc
- test/core/util/subprocess_windows.cc
- test/core/util/test_config.cc
diff --git a/config.m4 b/config.m4
index 97800cc15e9..1a1a125b743 100644
--- a/config.m4
+++ b/config.m4
@@ -373,6 +373,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gpr/tmpfile_windows.cc \
src/core/lib/gpr/wrap_memcpy.cc \
src/core/lib/gprpp/arena.cc \
+ src/core/lib/gprpp/examine_stack.cc \
src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/global_config_env.cc \
src/core/lib/gprpp/host_port.cc \
diff --git a/config.w32 b/config.w32
index 8f2e6bc7827..366d530ea8a 100644
--- a/config.w32
+++ b/config.w32
@@ -340,6 +340,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\gpr\\tmpfile_windows.cc " +
"src\\core\\lib\\gpr\\wrap_memcpy.cc " +
"src\\core\\lib\\gprpp\\arena.cc " +
+ "src\\core\\lib\\gprpp\\examine_stack.cc " +
"src\\core\\lib\\gprpp\\fork.cc " +
"src\\core\\lib\\gprpp\\global_config_env.cc " +
"src\\core\\lib\\gprpp\\host_port.cc " +
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index f832e89f829..da0642a77f0 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -496,6 +496,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
+ 'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/global_config.h',
'src/core/lib/gprpp/global_config_custom.h',
@@ -1099,6 +1100,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
+ 'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/global_config.h',
'src/core/lib/gprpp/global_config_custom.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 1a84b55e45d..5ece0224b01 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -820,6 +820,8 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
+ 'src/core/lib/gprpp/examine_stack.cc',
+ 'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/global_config.h',
@@ -1627,6 +1629,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/debug_location.h',
'src/core/lib/gprpp/dual_ref_counted.h',
+ 'src/core/lib/gprpp/examine_stack.h',
'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/global_config.h',
'src/core/lib/gprpp/global_config_custom.h',
@@ -2010,8 +2013,6 @@ Pod::Spec.new do |s|
'test/core/util/debugger_macros.h',
'test/core/util/eval_args_mock_endpoint.cc',
'test/core/util/eval_args_mock_endpoint.h',
- 'test/core/util/examine_stack.cc',
- 'test/core/util/examine_stack.h',
'test/core/util/fuzzer_util.cc',
'test/core/util/fuzzer_util.h',
'test/core/util/grpc_profiler.cc',
@@ -2037,6 +2038,8 @@ Pod::Spec.new do |s|
'test/core/util/resolve_localhost_ip46.h',
'test/core/util/slice_splitter.cc',
'test/core/util/slice_splitter.h',
+ 'test/core/util/stack_tracer.cc',
+ 'test/core/util/stack_tracer.h',
'test/core/util/subprocess.h',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
diff --git a/grpc.gemspec b/grpc.gemspec
index d4ade6aa93d..7d11e2ac64f 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -737,6 +737,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/atomic.h )
s.files += %w( src/core/lib/gprpp/debug_location.h )
s.files += %w( src/core/lib/gprpp/dual_ref_counted.h )
+ s.files += %w( src/core/lib/gprpp/examine_stack.cc )
+ s.files += %w( src/core/lib/gprpp/examine_stack.h )
s.files += %w( src/core/lib/gprpp/fork.cc )
s.files += %w( src/core/lib/gprpp/fork.h )
s.files += %w( src/core/lib/gprpp/global_config.h )
diff --git a/grpc.gyp b/grpc.gyp
index db3c7e9686a..741dad28e9d 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -379,6 +379,7 @@
'target_name': 'gpr',
'type': 'static_library',
'dependencies': [
+ 'absl/types:optional',
'absl/time:time',
'absl/synchronization:synchronization',
'absl/strings:strings',
@@ -421,6 +422,7 @@
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
'src/core/lib/gprpp/arena.cc',
+ 'src/core/lib/gprpp/examine_stack.cc',
'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/global_config_env.cc',
'src/core/lib/gprpp/host_port.cc',
@@ -1002,7 +1004,6 @@
'test/core/util/cmdline.cc',
'test/core/util/debugger_macros.cc',
'test/core/util/eval_args_mock_endpoint.cc',
- 'test/core/util/examine_stack.cc',
'test/core/util/fuzzer_util.cc',
'test/core/util/grpc_profiler.cc',
'test/core/util/histogram.cc',
@@ -1016,6 +1017,7 @@
'test/core/util/reconnect_server.cc',
'test/core/util/resolve_localhost_ip46.cc',
'test/core/util/slice_splitter.cc',
+ 'test/core/util/stack_tracer.cc',
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
@@ -1040,7 +1042,6 @@
'test/core/util/cmdline.cc',
'test/core/util/debugger_macros.cc',
'test/core/util/eval_args_mock_endpoint.cc',
- 'test/core/util/examine_stack.cc',
'test/core/util/fuzzer_util.cc',
'test/core/util/grpc_profiler.cc',
'test/core/util/histogram.cc',
@@ -1054,6 +1055,7 @@
'test/core/util/reconnect_server.cc',
'test/core/util/resolve_localhost_ip46.cc',
'test/core/util/slice_splitter.cc',
+ 'test/core/util/stack_tracer.cc',
'test/core/util/subprocess_posix.cc',
'test/core/util/subprocess_windows.cc',
'test/core/util/test_config.cc',
diff --git a/package.xml b/package.xml
index 25fa57adc08..4f2cdb32d5b 100644
--- a/package.xml
+++ b/package.xml
@@ -717,6 +717,8 @@
+
+
diff --git a/src/core/lib/gpr/log_linux.cc b/src/core/lib/gpr/log_linux.cc
index bf07822a213..69fa45c9cf7 100644
--- a/src/core/lib/gpr/log_linux.cc
+++ b/src/core/lib/gpr/log_linux.cc
@@ -38,8 +38,11 @@
#include
#include
#include
+
#include
+
#include "absl/strings/str_format.h"
+#include "src/core/lib/gprpp/examine_stack.h"
static long sys_gettid(void) { return syscall(__NR_gettid); }
@@ -89,7 +92,17 @@ void gpr_default_log(gpr_log_func_args* args) {
std::string prefix = absl::StrFormat(
"%s%s.%09" PRId32 " %7ld %s:%d]", gpr_log_severity_string(args->severity),
time_buffer, now.tv_nsec, tid, display_file, args->line);
- fprintf(stderr, "%-60s %s\n", prefix.c_str(), args->message);
+
+ absl::optional stack_trace =
+ args->severity >= GPR_LOG_SEVERITY_ERROR
+ ? grpc_core::GetCurrentStackTrace()
+ : absl::nullopt;
+ if (stack_trace) {
+ fprintf(stderr, "%-60s %s\n%s\n", prefix.c_str(), args->message,
+ stack_trace->c_str());
+ } else {
+ fprintf(stderr, "%-60s %s\n", prefix.c_str(), args->message);
+ }
}
#endif /* GPR_LINUX_LOG */
diff --git a/src/core/lib/gpr/log_posix.cc b/src/core/lib/gpr/log_posix.cc
index 3fff01a624e..de293ce0b79 100644
--- a/src/core/lib/gpr/log_posix.cc
+++ b/src/core/lib/gpr/log_posix.cc
@@ -30,7 +30,9 @@
#include
#include
#include
+
#include "absl/strings/str_format.h"
+#include "src/core/lib/gprpp/examine_stack.h"
static intptr_t sys_gettid(void) { return (intptr_t)pthread_self(); }
@@ -87,7 +89,17 @@ void gpr_default_log(gpr_log_func_args* args) {
std::string prefix = absl::StrFormat(
"%s%s.%09d %7" PRIdPTR " %s:%d]", gpr_log_severity_string(args->severity),
time_buffer, (int)(now.tv_nsec), sys_gettid(), display_file, args->line);
- fprintf(stderr, "%-70s %s\n", prefix.c_str(), args->message);
+
+ absl::optional stack_trace =
+ args->severity >= GPR_LOG_SEVERITY_ERROR
+ ? grpc_core::GetCurrentStackTrace()
+ : absl::nullopt;
+ if (stack_trace) {
+ fprintf(stderr, "%-70s %s\n%s\n", prefix.c_str(), args->message,
+ stack_trace->c_str());
+ } else {
+ fprintf(stderr, "%-70s %s\n", prefix.c_str(), args->message);
+ }
}
#endif /* defined(GPR_POSIX_LOG) */
diff --git a/src/core/lib/gpr/log_windows.cc b/src/core/lib/gpr/log_windows.cc
index 060be572b80..bed202fab7a 100644
--- a/src/core/lib/gpr/log_windows.cc
+++ b/src/core/lib/gpr/log_windows.cc
@@ -31,6 +31,7 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/string_windows.h"
+#include "src/core/lib/gprpp/examine_stack.h"
void gpr_log(const char* file, int line, gpr_log_severity severity,
const char* format, ...) {
@@ -92,10 +93,21 @@ void gpr_default_log(gpr_log_func_args* args) {
strcpy(time_buffer, "error:strftime");
}
- fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
- gpr_log_severity_string(args->severity), time_buffer,
- (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
- args->message);
+ absl::optional stack_trace =
+ args->severity >= GPR_LOG_SEVERITY_ERROR
+ ? grpc_core::GetCurrentStackTrace()
+ : absl::nullopt;
+ if (stack_trace) {
+ fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n%s\n",
+ gpr_log_severity_string(args->severity), time_buffer,
+ (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
+ args->message, stack_trace->c_str());
+ } else {
+ fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n",
+ gpr_log_severity_string(args->severity), time_buffer,
+ (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line,
+ args->message);
+ }
fflush(stderr);
}
diff --git a/src/core/lib/gprpp/examine_stack.cc b/src/core/lib/gprpp/examine_stack.cc
new file mode 100644
index 00000000000..1c5d93aeb52
--- /dev/null
+++ b/src/core/lib/gprpp/examine_stack.cc
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2020 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
+
+#include "src/core/lib/gprpp/examine_stack.h"
+
+namespace grpc_core {
+
+gpr_current_stack_trace_func g_current_stack_trace_provider = nullptr;
+
+gpr_current_stack_trace_func GetCurrentStackTraceProvider() {
+ return g_current_stack_trace_provider;
+}
+
+void SetCurrentStackTraceProvider(
+ gpr_current_stack_trace_func current_stack_trace_provider) {
+ g_current_stack_trace_provider = current_stack_trace_provider;
+}
+
+absl::optional GetCurrentStackTrace() {
+ if (g_current_stack_trace_provider != nullptr) {
+ return g_current_stack_trace_provider();
+ }
+ return absl::nullopt;
+}
+
+} // namespace grpc_core
diff --git a/src/core/lib/gprpp/examine_stack.h b/src/core/lib/gprpp/examine_stack.h
new file mode 100644
index 00000000000..00ba1fc1070
--- /dev/null
+++ b/src/core/lib/gprpp/examine_stack.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2020 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_EXAMINE_STACK_H
+#define GRPC_CORE_LIB_GPRPP_EXAMINE_STACK_H
+
+#include
+
+#include
+#include
+
+#include "absl/types/optional.h"
+
+namespace grpc_core {
+
+typedef std::string (*gpr_current_stack_trace_func)();
+
+// Returns a current_stack_trace_provider.
+gpr_current_stack_trace_func GetCurrentStackTraceProvider();
+
+// Sets current_stack_trace_provider which provides a current-stack trace.
+void SetCurrentStackTraceProvider(
+ gpr_current_stack_trace_func current_stack_trace_provider);
+
+// Returns the current stack trace as a string via current_stack_trace_provider
+// If current_stack_trace_provider is not set, it returns absl::nullopt.
+absl::optional GetCurrentStackTrace();
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_EXAMINE_STACK_H */
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 0881c4b42ea..89152245f19 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -349,6 +349,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
'src/core/lib/gprpp/arena.cc',
+ 'src/core/lib/gprpp/examine_stack.cc',
'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/global_config_env.cc',
'src/core/lib/gprpp/host_port.cc',
diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD
index 9b51c3749db..0db133bebd0 100644
--- a/test/core/gprpp/BUILD
+++ b/test/core/gprpp/BUILD
@@ -19,6 +19,24 @@ licenses(["notice"]) # Apache v2
grpc_package(name = "test/core/gprpp")
+grpc_cc_test(
+ name = "examine_stack_test",
+ srcs = ["examine_stack_test.cc"],
+ external_deps = [
+ "absl/debugging:stacktrace",
+ "absl/debugging:symbolize",
+ "gtest",
+ ],
+ language = "C++",
+ # TODO(https://github.com/grpc/grpc/issues/24627): Disable this on Windows
+ tags = ["no_windows"],
+ uses_polling = False,
+ deps = [
+ "//:gpr",
+ "//test/core/util:grpc_test_util",
+ ],
+)
+
grpc_cc_test(
name = "fork_test",
srcs = ["fork_test.cc"],
diff --git a/test/core/gprpp/examine_stack_test.cc b/test/core/gprpp/examine_stack_test.cc
new file mode 100644
index 00000000000..0d52a037ea4
--- /dev/null
+++ b/test/core/gprpp/examine_stack_test.cc
@@ -0,0 +1,82 @@
+/*
+ *
+ * Copyright 2020 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/gprpp/examine_stack.h"
+
+#include
+#include
+
+#include
+
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+
+#include
+
+namespace {
+
+std::string SimpleCurrentStackTraceProvider() { return "stacktrace"; }
+
+std::string AbseilCurrentStackTraceProvider() {
+ std::string result = "Stack trace:\n";
+ constexpr int kNumStackFrames = 10;
+ void* stack[kNumStackFrames];
+ int frame_sizes[kNumStackFrames];
+ int depth = absl::GetStackFrames(stack, frame_sizes, kNumStackFrames, 1);
+ for (int i = 0; i < depth; i++) {
+ char tmp[1024];
+ const char* symbol = "(unknown)";
+ if (absl::Symbolize(stack[i], tmp, sizeof(tmp))) {
+ symbol = tmp;
+ }
+ result += symbol;
+ result += +"\n";
+ }
+ return result;
+}
+
+} // namespace
+
+TEST(ExamineStackTest, NullStackProvider) {
+ grpc_core::SetCurrentStackTraceProvider(nullptr);
+ EXPECT_EQ(grpc_core::GetCurrentStackTraceProvider(), nullptr);
+ EXPECT_EQ(grpc_core::GetCurrentStackTrace(), absl::nullopt);
+}
+
+TEST(ExamineStackTest, SimpleStackProvider) {
+ grpc_core::SetCurrentStackTraceProvider(&SimpleCurrentStackTraceProvider);
+ EXPECT_NE(grpc_core::GetCurrentStackTraceProvider(), nullptr);
+ EXPECT_EQ(grpc_core::GetCurrentStackTrace(), "stacktrace");
+}
+
+TEST(ExamineStackTest, AbseilStackProvider) {
+ grpc_core::SetCurrentStackTraceProvider(&AbseilCurrentStackTraceProvider);
+ EXPECT_NE(grpc_core::GetCurrentStackTraceProvider(), nullptr);
+ const absl::optional stack_trace =
+ grpc_core::GetCurrentStackTrace();
+ EXPECT_NE(stack_trace, absl::nullopt);
+ gpr_log(GPR_INFO, "stack_trace=%s", stack_trace->c_str());
+ EXPECT_TRUE(stack_trace->find("GetCurrentStackTrace") != -1);
+}
+
+int main(int argc, char** argv) {
+ absl::InitializeSymbolizer(argv[0]);
+ ::testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index 9d2d27fac8c..0711aaefc48 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -39,7 +39,6 @@ grpc_cc_library(
srcs = [
"cmdline.cc",
"eval_args_mock_endpoint.cc",
- "examine_stack.cc",
"fuzzer_util.cc",
"grpc_profiler.cc",
"histogram.cc",
@@ -63,7 +62,6 @@ grpc_cc_library(
hdrs = [
"cmdline.h",
"eval_args_mock_endpoint.h",
- "examine_stack.h",
"fuzzer_util.h",
"grpc_profiler.h",
"histogram.h",
@@ -89,12 +87,12 @@ grpc_cc_library(
],
external_deps = [
"absl/debugging:failure_signal_handler",
- "absl/debugging:stacktrace",
"absl/debugging:symbolize",
],
language = "C++",
deps = [
":grpc_debugger_macros",
+ ":stack_tracer",
"//:gpr",
"//:grpc_base_c",
"//:grpc_common",
@@ -171,6 +169,43 @@ sh_library(
srcs = ["run_with_poller.sh"],
)
+grpc_cc_library(
+ name = "stack_tracer",
+ srcs = [
+ "stack_tracer.cc",
+ ],
+ hdrs = [
+ "stack_tracer.h",
+ ],
+ external_deps = [
+ "absl/debugging:stacktrace",
+ "absl/debugging:symbolize",
+ ],
+ language = "C++",
+ deps = [
+ "//:grpc_common",
+ ],
+)
+
+grpc_cc_test(
+ name = "stack_tracer_test",
+ srcs = [
+ "stack_tracer_test.cc",
+ ],
+ external_deps = [
+ "absl/debugging:symbolize",
+ "gtest",
+ ],
+ language = "C++",
+ # TODO(https://github.com/grpc/grpc/issues/24627): Disable this on Windows
+ tags = ["no_windows"],
+ uses_polling = False,
+ deps = [
+ ":grpc_test_util",
+ ":stack_tracer",
+ ],
+)
+
grpc_cc_library(
name = "test_lb_policies",
testonly = 1,
diff --git a/test/core/util/examine_stack.cc b/test/core/util/stack_tracer.cc
similarity index 91%
rename from test/core/util/examine_stack.cc
rename to test/core/util/stack_tracer.cc
index 9321aca789f..228e5bbe726 100644
--- a/test/core/util/examine_stack.cc
+++ b/test/core/util/stack_tracer.cc
@@ -18,7 +18,7 @@
#include
-#include "test/core/util/examine_stack.h"
+#include "test/core/util/stack_tracer.h"
#include
#include
@@ -26,6 +26,8 @@
#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
+#include "src/core/lib/gprpp/examine_stack.h"
+
namespace {
static constexpr int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
@@ -87,8 +89,9 @@ static void DebugWriteToString(const char* data, void* str) {
} // namespace
namespace grpc_core {
+namespace testing {
-std::string CurrentStackTrace() {
+std::string GetCurrentStackTrace() {
std::string result = "Stack trace:\n";
constexpr int kNumStackFrames = 32;
void* stack[kNumStackFrames];
@@ -99,4 +102,10 @@ std::string CurrentStackTrace() {
return result;
}
+void InitializeStackTracer(const char* argv0) {
+ absl::InitializeSymbolizer(argv0);
+ grpc_core::SetCurrentStackTraceProvider(&GetCurrentStackTrace);
+}
+
+} // namespace testing
} // namespace grpc_core
diff --git a/test/core/util/examine_stack.h b/test/core/util/stack_tracer.h
similarity index 54%
rename from test/core/util/examine_stack.h
rename to test/core/util/stack_tracer.h
index bed5169b9b9..6b3b92ec4cf 100644
--- a/test/core/util/examine_stack.h
+++ b/test/core/util/stack_tracer.h
@@ -24,11 +24,25 @@
#include
namespace grpc_core {
+namespace testing {
-// Return the current stack trace as a string (on multiple lines, beginning with
-// "Stack trace:\n")
-std::string CurrentStackTrace();
+// Returns the current stack trace as a string. To have symbolized stack-traces,
+// InitializeStackTracer needs to be called beforehand.
+//
+// Example of stack-trace is
+// Stack trace:
+// @ 0x405b0f 192 StackTracerTest_Basic_Test::TestBody()
+// @ 0x7fbace6baf75 288 testing::internal::RunAllTests()
+// @ 0x7fbace6baa93 144 testing::UnitTest::Run()
+// @ 0x405d4d 64 main
+//
+std::string GetCurrentStackTrace();
+// Initializes a stack tracer so that GetCurrentStackTrace can work.
+// This inits debug symbols and sets this as a gRPC stack-trace provider.
+void InitializeStackTracer(const char* argv0);
+
+} // namespace testing
} // namespace grpc_core
#endif /* GRPC_TEST_CORE_UTIL_EXAMINE_STACK_H */
diff --git a/test/core/util/stack_tracer_test.cc b/test/core/util/stack_tracer_test.cc
new file mode 100644
index 00000000000..79fe8e27a79
--- /dev/null
+++ b/test/core/util/stack_tracer_test.cc
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2020 the 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 "test/core/util/stack_tracer.h"
+
+#include
+#include
+
+#include "absl/debugging/symbolize.h"
+
+#include
+
+#include "test/core/util/test_config.h"
+
+TEST(StackTracerTest, Basic) {
+ std::string stack_trace = grpc_core::testing::GetCurrentStackTrace();
+ gpr_log(GPR_INFO, "stack_trace=%s", stack_trace.c_str());
+ EXPECT_TRUE(stack_trace.find("Basic") != -1);
+}
+
+int main(int argc, char** argv) {
+ grpc::testing::TestEnvironment env(argc, argv);
+ testing::InitGoogleTest(&argc, argv);
+ int ret = RUN_ALL_TESTS();
+ return ret;
+}
diff --git a/test/core/util/test_config.cc b/test/core/util/test_config.cc
index ccc30bf19d2..c677a5365c1 100644
--- a/test/core/util/test_config.cc
+++ b/test/core/util/test_config.cc
@@ -32,7 +32,9 @@
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/examine_stack.h"
#include "src/core/lib/surface/init.h"
+#include "test/core/util/stack_tracer.h"
#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"
@@ -378,7 +380,7 @@ void grpc_test_init(int argc, char** argv) {
// https://github.com/grpc/grpc/issues/24178
install_crash_handler();
#else
- absl::InitializeSymbolizer(argv[0]);
+ grpc_core::testing::InitializeStackTracer(argv[0]);
absl::FailureSignalHandlerOptions options;
absl::InstallFailureSignalHandler(options);
#endif
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 4bca2c7f459..90aadee82c6 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1669,6 +1669,8 @@ src/core/lib/gprpp/arena.h \
src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/dual_ref_counted.h \
+src/core/lib/gprpp/examine_stack.cc \
+src/core/lib/gprpp/examine_stack.h \
src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/global_config.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index b3459384268..10de1cb9e2a 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1510,6 +1510,8 @@ src/core/lib/gprpp/arena.h \
src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/debug_location.h \
src/core/lib/gprpp/dual_ref_counted.h \
+src/core/lib/gprpp/examine_stack.cc \
+src/core/lib/gprpp/examine_stack.h \
src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/global_config.h \
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 2c1bf4643e7..37c76be8244 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -4409,6 +4409,28 @@
],
"uses_polling": false
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "examine_stack_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "uses_polling": false
+ },
{
"args": [],
"benchmark": false,
@@ -5667,6 +5689,28 @@
],
"uses_polling": true
},
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "stack_tracer_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix"
+ ],
+ "uses_polling": false
+ },
{
"args": [],
"benchmark": false,