Apache error_log 不直接捕获子进程崩溃信号,而是记录主进程通过 waitpid() 捕获到的子进程因 SIGSEGV 等信号终止的日志,如“AH00052: child pid 12346 exit signal Segmentation fault (11)”。

Apache 的 error_log 本身不直接“捕获”子进程崩溃信号,它只是记录 Apache 主进程或子进程在运行中产生的日志信息,包括由操作系统发送给子进程的致命信号(如 SIGSEGV、SIGBUS、SIGABRT 等)所触发的异常终止事件。
Apache 如何感知并记录子进程崩溃
当 Apache 的工作进程(如 prefork 的子进程、worker/event 模型下的线程/子进程)因非法内存访问、空指针解引用、JVM 崩溃(若集成 Java 如 via mod_jk/mod_proxy_ajp)等原因收到致命信号时:
- 操作系统会终止该进程,并向父进程(Apache 主进程)发送
SIGCHLD通知; - Apache 主进程通过
waitpid()等系统调用获取子进程退出状态; - 若子进程是因信号终止(即
WIFSIGNALED(status)为真),Apache 会将信号名(如segmentation fault (11))写入error_log,典型格式如下:
Java 相关崩溃的特殊性(如使用 mod_jk 或嵌入式 JVM)
若 Apache 通过 mod_jk 连接 Tomcat,或使用 mod_proxy_ajp,那么 Apache 子进程本身通常不执行 Java 字节码——崩溃更可能发生在后端 JVM 进程中。此时:
- Apache
error_log不会记录 JVM 内部的NullPointerException等 Java 异常; - 但若 JVM 因本地库错误(如 JNI bug)、堆外内存破坏、JRE 本身缺陷导致收到
SIGSEGV,则 JVM 进程崩溃; - 此时 Apache 可能记录连接中断、超时或 AJP 协议错误(如
ajp_read_header: ajp_ilink_receive failed),而非直接信号名; - 真正信号级崩溃日志需查看 JVM 自身的
hs_err_pid*.log或系统dmesg输出。
增强崩溃诊断的实用建议
仅靠 error_log 往往不足以定位 Java 关联的底层崩溃,需组合手段:
- 开启 Apache 的
LogLevel debug(临时),观察子进程 fork、exit、signal 相关细节; - 为 JVM 配置崩溃日志:
-XX:+UnlockDiagnosticVMOptions -XX:ErrorFile=/var/log/java/hs_err_%p.log; - 检查系统日志:
dmesg -T | grep -i "segfault\|trapped\|killed process",确认是否被 OOM Killer 终止; - 对 native 代码(如 JNI 库)启用 AddressSanitizer 或 Valgrind(测试环境);
- 避免在 Apache 子进程中直接嵌入 JVM(如旧版 mod_jk 的 in-process 模式),优先采用进程分离架构。
注意 signal 日志的局限性
error_log 中的 exit signal Segmentation fault (11) 是结果,不是根因:
- 它不包含调用栈、寄存器状态或内存转储;
- 无法区分是 Apache 自身模块、第三方模块(如 mod_php)、还是 Java 网关组件引发;
- 多线程环境下,信号可能由任意线程触发,主进程日志无法精确定位线程上下文。
要深入分析,必须结合 core dump(需开启 ulimit -c unlimited 并配置 /proc/sys/kernel/core_pattern)、GDB 和 JVM hs_err 文件交叉验证。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










