Go Runtime(七):Signal与cgo线程管理

本文源码基线为 Go 1.26.2、Linux/amd64。Signal 的编号、trampoline 和上下文结构具有平台差异;本文只把 Unix/Linux 主线作为具体实现,Windows 异常和 IOCP 回调需要单独对照平台文件。 CPU profile 或崩溃栈可能呈现一个反直觉结果:信号打断了任意指令,C 创建的 pthread 也出现在 Go 调用栈里,但 runtime 仍必须识别当前线程、当前 G 和可扫描的栈。信号和 cgo 都会打破普通 Go 调用链的假设:信号可以异步到达,C 代码可能阻塞、修改线程状态,甚至从一个非 Go 创建的线程回调 Go。 本文先解释异步信号入口,再沿 Go 调 C、C 回调 Go 的调用链前进,最后回答外部线程进入 Go 时 M、g0、gsignal 和 TLS 从哪里来。runtime 必须在这些边界上重新建立可识别的线程、栈和执行现场,同时避免在不安全上下文中执行分配、加锁或调度操作。 异步信号边界 Signal承担哪些职责 Go runtime 使用或处理信号的目的并不相同: 把 SIGINT、SIGTERM 等转交给 os/signal。 将某些同步 fault 转换为 Go panic。 用异步信号抢占长时间运行的 goroutine。 采样 SIGPROF 生成 CPU profile。 在 cgo 场景与 C 安装的 handler 协作。 对致命信号打印 traceback 并退出。 因此不能笼统地说“Go 捕获了信号”。同一个 handler 入口会根据 signal 类型、发生线程和当前 G/M 状态走不同分支。 ...

August 18, 2026