Abseil Stack trace·failure_signal_handler
#왜 crash 시 stack trace인가
production에서 SIGSEGV·SIGABRT가 일어났을 때 어디서 죽었는지 알 수 없으면 디버깅이 불가능하다. core dump가 있더라도 분석에 시간이 걸린다. Abseil의 failure signal handler는 프로세스가 죽기 직전에 stack을 찍어 stderr/로그에 남긴다.
#include "absl/debugging/failure_signal_handler.h"#include "absl/debugging/symbolize.h"
int main(int argc, char** argv) { absl::InitializeSymbolizer(argv[0]); absl::FailureSignalHandlerOptions opts; absl::InstallFailureSignalHandler(opts);
// ... 이후 SIGSEGV·CHECK 실패 등이 일어나면 stack trace 출력}두 줄로 production crash diagnostic이 켜진다.
#어떤 signal을 처리하나
기본적으로 다음 signal에 hooked.
| Signal | 의미 |
|---|---|
SIGSEGV | invalid memory access |
SIGILL | invalid instruction |
SIGFPE | floating point error |
SIGABRT | abort (CHECK 실패) |
SIGTERM | termination (옵션) |
SIGBUS | bus error |
SIGTRAP | trap |
각 signal에 대해 signal handler가 stack을 찍고 원래 handler에게 위임 → 정상 종료 흐름 유지.
#InitializeSymbolizer — 심볼 매핑
InitializeSymbolizer(argv[0])는 실행 파일을 읽어 address → 함수 이름 매핑을 준비한다. 호출하지 않으면 stack trace에 raw 주소(0x12345678)만 남는다.
// 회피absl::InstallFailureSignalHandler({});// SIGSEGV 시: "0x7f8a3c1b2d40" — 의미 없음
// Goodabsl::InitializeSymbolizer(argv[0]);absl::InstallFailureSignalHandler({});// SIGSEGV 시: "myapp::Server::HandleRequest(Request const&)" 같이 풀림stripped binary는 함수 이름이 일부만 풀린다. release 빌드에서도 디버그 정보 분리 (-g + objcopy --only-keep-debug) 패턴이면 풀 수 있다.
#GetStackTrace — 직접 호출
crash 외에도 임의 시점에 stack을 캡처할 수 있다.
#include "absl/debugging/stacktrace.h"
void DumpStack() { constexpr int kMax = 64; void* frames[kMax]; int n = absl::GetStackTrace(frames, kMax, /*skip_count=*/1);
for (int i = 0; i < n; ++i) { char buf[256]; if (absl::Symbolize(frames[i], buf, sizeof(buf))) { LOG(INFO) << " " << buf; } else { LOG(INFO) << " " << frames[i]; } }}leak 진단, race 발견 시 누가 호출했는지 등 임의 진단에 활용.
#FailureSignalHandlerOptions
struct FailureSignalHandlerOptions { bool symbolize_stacktrace = true; bool use_alternate_stack = true; // signal handler가 별도 스택 사용 int alarm_on_failure_secs = 3; // 핸들러가 hang하면 N초 후 abort
void (*writerfn)(const char*) = nullptr; // 출력 함수 커스터마이즈 void (*call_previous_handler)(int signo) = nullptr;};| 옵션 | 권장값 | 비고 |
|---|---|---|
symbolize_stacktrace | true | 함수 이름 풀이 |
use_alternate_stack | true | stack overflow 후에도 작동 |
alarm_on_failure_secs | 3~10 | 무한 hang 방지 |
writerfn | nullptr (기본 stderr) | custom logger로 보낼 때만 |
#use_alternate_stack — stack overflow 대비
stack overflow로 SIGSEGV가 나면 기존 스택이 가득 차서 핸들러도 못 돈다. use_alternate_stack = true는 별도 페이지에 핸들러 전용 스택을 둬서 이걸 막는다.
#CHECK 실패와의 연동
CHECK(...) 실패 시 내부적으로 abort() → SIGABRT → 우리가 등록한 handler. 따라서 CHECK 실패도 자동으로 stack trace가 함께 남는다.
CHECK(ptr != nullptr) << "internal";// 실패 시:// F20260525 13:00:00 12345 myfile.cc:42] Check failed: ptr != nullptr internal// *** Check failure stack trace: ***// absl::log_internal::LogMessage::Flush()// MyClass::Init()// main#출력 라우팅 — writerfn
기본은 stderr. file/syslog로 보내려면 writerfn을 등록.
void WriteToFile(const char* s) { static int fd = ::open("/var/log/crash.log", O_CREAT | O_WRONLY | O_APPEND, 0644); ::write(fd, s, strlen(s));}
absl::FailureSignalHandlerOptions opts;opts.writerfn = WriteToFile;absl::InstallFailureSignalHandler(opts);writerfn은 async-signal-safe 해야 한다. malloc·printf·LOG 등은 금지. write(2) 직접 호출만 안전.
#멀티스레드 환경
failure handler는 죽은 스레드만 stack을 찍는다. 다른 스레드의 상태는 모름. 추가 thread state가 필요하면:
opts.call_previous_handler = ExtendedDumper; // 이전 handler 호출 후 추가 작업라이브러리 함수와 충돌하지 않도록 가능한 최소한 만.
#작은 예시 — server boot
int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv);
// 1. symbolizer 먼저 — failure handler가 의존 absl::InitializeSymbolizer(argv[0]);
// 2. failure handler absl::FailureSignalHandlerOptions opts; opts.use_alternate_stack = true; opts.alarm_on_failure_secs = 5; absl::InstallFailureSignalHandler(opts);
// 3. 로그 초기화 absl::InitializeLog();
LOG(INFO) << "boot complete"; RunServer(); return 0;}순서 중요: symbolize → failure handler → log.
#회피 패턴
// 회피 — argv[0] 안 넘김absl::InitializeSymbolizer(""); // ❌ 심볼 풀이 안 됨
// Goodabsl::InitializeSymbolizer(argv[0]);// 회피 — handler 안에서 LOGopts.writerfn = [](const char* s) { LOG(ERROR) << s; }; // ❌ async-signal-unsafe
// Good — write 직접opts.writerfn = [](const char* s) { ::write(STDERR_FILENO, s, strlen(s)); };// 회피 — release 빌드에서 디버그 정보 모두 strip// strip myapp # ❌ 함수 이름 못 풉// → debug symbol 분리 패턴 사용#정리
InitializeSymbolizer(argv[0])+InstallFailureSignalHandler(opts)— production crash diagnostic.- SIGSEGV/SIGABRT/SIGFPE 등 자동 hook. CHECK 실패도 함께 처리.
use_alternate_stack— stack overflow 대비.alarm_on_failure_secs— hang 방지.GetStackTrace/Symbolize로 임의 시점 stack 캡처 가능.writerfn은 async-signal-safe 해야 함 — write(2)만.
#다음 장 예고
Part 12-01: ABSL_FLAG 정의 — command-line flag.
#관련 항목
- Part 11-01: LOG, VLOG, CHECK — CHECK 실패
- Part 11-02: LogSink
- Part 2-07: raw_logging — async-signal-safe logging
- 원문 — Failure Signal Handler
Abseil Code Review · 63 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
Abseil LogEntry·structured logging
absl::LogEntry — 한 로그 항목의 메타데이터(severity, timestamp, source location, message). 구조화 로깅의 기반.
같은 시리즈에서 이어 읽기
Abseil LogSink 분석
absl::LogSink — 출력 destination 커스터마이징. 파일·syslog·원격 collector·테스트 캡처.
같은 시리즈에서 이어 읽기
Abseil LOG·VLOG·CHECK 분석
Abseil logging 기본 매크로 — severity, verbose level, fatal check. glog의 후속이자 Google 표준.
같은 시리즈에서 이어 읽기