tl; dr:当Perl httpd进程内存不足时,如何转储perl堆栈跟踪。
我们有一台mod_perl 2服务器,Perl 5.8.8,RHEL 5.6,Linux 2.6.18。
非常偶然且不可预测,子httpd进程开始以惊人的速度耗尽所有可用内存。我们至少使用过BSD :: Resource :: setrlimit(RLIMIT_VMEM,...),因此在关闭服务器之前,进程会因“内存不足”而死亡。
我们不知道代码在哪里发生,如果没有数小时的负载测试就很难重现。
我们真正喜欢的是在进程耗尽内存之前获取 Perl堆栈跟踪的方法,因此我们知道导致此问题的代码。不幸的是,“内存不足”是untrappable error。
以下是我正在考虑的选项,每个选项都有其缺点:
1)使用$^M emergency memory pool。要求我们使用-DPERL_EMERGENCY_SBRK和-Dusemymalloc重新编译perl。
2)放入大量日志语句,然后分析日志以查看流程停止的位置。
3)编写一个不断扫描httpd进程池的外部脚本,如果它看到一个使用大量内存的脚本,则向它发送一个USR2信号(我们已安排转储堆栈跟踪)。
4)不知何故,进程会持续监视自己的内存,并在内存变高但“内存不足”错误之前转储堆栈跟踪。
谢谢!
乔恩
答案 0 :(得分:3)
您可以使用mod_backtrace
获得回溯,请参阅Andy Millar's introduction。回溯是在C级别,所以你需要
答案 1 :(得分:2)
您可以尝试使用LD_PRELOAD加载malloc / free的自定义版本。没有必要重新链接或重新编译任何东西。只需将LD_PRELOAD设置为具有与malloc相同的接口的.so,并且在运行可执行文件时将加载此预加载版本的malloc而不是正常的系统malloc。例如,这是使用efence检测内存错误的常用策略。
我不认为efence在这里对你有用,因为那是用于检测内存覆盖,而不是调试内存不足(我不知道它在OOM上做了什么)。我想你可能想看看failmalloc。我从来没有使用过这个,但听起来它可能会做你想要的(我只是浏览了头版)。
答案 2 :(得分:0)
根据 Practical mod_perl ,将Apache::Debug level => 4;
添加到您的代码将导致它分配$ ^ M紧急池并致电Carp::confess()
。