我今天遇到了一些服务器问题,现在我将其归结为它无法摆脱出现段错误的进程。
在进程出现 seg-fault 后,进程只是一直挂起,而不是被杀死。
应该导致错误 Segmentation fault (core dumped) 的测试.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
buf = malloc(1<<31);
fgets(buf, 1024, stdin);
printf("%s\n", buf);
return 1;
}
使用 gcc segfault.c -o segfault && chmod +x segfault 编译和设置权限.
在有问题的服务器上运行此程序(并按回车键 1 次)会导致它挂起。我还在另一台具有相同内核版本(和大多数相同软件包)的服务器上运行它,它得到了 seg-fault 然后退出。
这是运行 strace ./segfault 后的最后几行在两台服务器上。
服务器错误
"\n", 1024) = 1
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
# It hangs here....
工作服务器
"\n", 1024) = 1
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
root@server { ~ }# echo $?
139
当进程挂起时(在它发生段错误之后),这就是它的样子。
无法 ^c 它
root@server { ~ }# ./segfault
^C^C^C
来自 ps aux 的条目
root 22944 0.0 0.0 69700 444 pts/18 S+ 15:39 0:00 ./segfault
cat/proc/22944/stack
[<ffffffff81223ca8>] do_coredump+0x978/0xb10
[<ffffffff810850c7>] get_signal_to_deliver+0x1c7/0x6d0
[<ffffffff81013407>] do_signal+0x57/0x6c0
[<ffffffff81013ad9>] do_notify_resume+0x69/0xb0
[<ffffffff8160bbfc>] retint_signal+0x48/0x8c
[<ffffffffffffffff>] 0xffffffffffffffff
另一个有趣的事情是我无法附加 strace到一个挂起的段错误进程。这样做实际上会使它被杀死。
root@server { ~ }# strace -p 1234
Process 1234 attached
+++ killed by SIGSEGV (core dumped) +++
ulimit -c 0坐下,ulimit -c , ulimit -H -c , 和 ulimit -S -c全部显示值 0
3.10.0-229.14.1.el7.x86_64 Red Hat Enterprise Linux Server release 7.1 (Maipo) 服务器在其他所有方面都在正常工作。
更新
关闭 abrt (systemctl stop abrtd.service) 解决了核心转储后进程已挂起的问题,以及新进程核心转储。再次启动 abrt 并没有恢复问题。
2016 年 1 月 26 日更新 我们遇到了一个看起来相似但又不完全相同的问题。用于测试的初始代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char *buf;
buf = malloc(1<<31);
fgets(buf, 1024, stdin);
printf("%s\n", buf);
return 1;
}
挂了。 cat /proc/<pid>/maps 的输出是
00400000-00401000 r-xp 00000000 fd:00 13143328 /root/segfault
00600000-00601000 r--p 00000000 fd:00 13143328 /root/segfault
00601000-00602000 rw-p 00001000 fd:00 13143328 /root/segfault
7f6c08000000-7f6c08021000 rw-p 00000000 00:00 0
7f6c08021000-7f6c0c000000 ---p 00000000 00:00 0
7f6c0fd5b000-7f6c0ff11000 r-xp 00000000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c0ff11000-7f6c10111000 ---p 001b6000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10111000-7f6c10115000 r--p 001b6000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10115000-7f6c10117000 rw-p 001ba000 fd:00 14284 /usr/lib64/libc-2.17.so
7f6c10117000-7f6c1011c000 rw-p 00000000 00:00 0
7f6c1011c000-7f6c1013d000 r-xp 00000000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c10330000-7f6c10333000 rw-p 00000000 00:00 0
7f6c1033b000-7f6c1033d000 rw-p 00000000 00:00 0
7f6c1033d000-7f6c1033e000 r--p 00021000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c1033e000-7f6c1033f000 rw-p 00022000 fd:00 14274 /usr/lib64/ld-2.17.so
7f6c1033f000-7f6c10340000 rw-p 00000000 00:00 0
7ffc13b5b000-7ffc13b7c000 rw-p 00000000 00:00 0 [stack]
7ffc13bad000-7ffc13baf000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
但是,触发段错误的较小 c 代码 ( int main(void){*(volatile char*)0=0;} ) 确实导致了段错误并且没有挂起...
最佳答案
警告 - 此答案包含许多基于手头不完整信息的假设。希望它仍然有用!
正如堆栈跟踪所示,内核正忙于创建崩溃进程的核心转储。
但是为什么这需要这么长时间?一个可能的解释是,您用于创建段错误的方法导致进程具有大量虚拟地址空间。
正如 M.M. 的评论中所指出的,表达式 1<31 的结果在="" c="" 标准中是未定义的,因此很难说传递给="" malloc="" 的实际值是什么,但基于后续行为我我假设这是一个很大的数字。="">31>
请注意,为了使 malloc 成功,您实际上不需要在系统中拥有这么多 RAM - 内核将扩展您进程的虚拟大小,但只有在您的程序实际访问该 RAM 时才会分配实际 RAM。
我相信对 malloc 的调用会成功,或者至少会返回,因为您在按 Enter 后声明它会出现段错误,因此在调用 fgets 之后也是如此。
在任何情况下,段错误都会导致内核执行核心转储。如果进程的虚拟大小很大,这可能需要很长时间,特别是如果内核决定转储所有页面,即使是那些从未被进程访问过的页面。我不确定它是否会这样做,但如果确实如此,并且系统中没有足够的 RAM,它就必须开始交换页面进出内存,以便将它们转储到核心转储中。这会产生高 IO 负载,从而导致进程看起来没有响应(并且整体系统性能会下降)。
您可以通过查看 abrtd 转储目录(可能是 /var/tmp/abrt,或检查 /etc/abrt/abrt.conf),您可以在其中找到已创建的核心转储(或者可能是部分核心转储)。
如果您能够重现该行为,那么您可以检查:
/proc/[pid]/maps查看进程的地址空间映射,看看是否真的很大sar,那么即使在重新启动 abrtd 之前的时间段内,您也可能会看到类似的信息。根据this bug report ,无论 ulimit 设置如何,abrtd 都会触发核心转储的收集。
对此有几种可能的解释。一方面,它取决于系统中可用 RAM 的数量。如果有足够的空闲 RAM 并且系统没有被推送到交换,那么大型进程的单个核心转储可能不会花费那么长时间,并且不会被视为挂起。
如果在您最初的实验中,您有多个处于这种状态的进程,那么症状会比仅让一个进程出现异常时的情况严重得多。
另一种可能性是 abrtd 的配置已更改但服务尚未重新加载,因此当您重新启动它时,它开始使用新配置,可能会改变它的行为。
也有可能是 yum 更新更新了 abrtd,但没有重新启动它,所以当你重新启动它时,新版本正在运行。
关于c++ - 分段故障本身挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33673592/
当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t
我是Ruby和这个网站的新手。下面两个函数是不同的,一个在函数外修改变量,一个不修改。defm1(x)x我想确保我理解正确-当调用m1时,对str的引用被复制并传递给将其视为x的函数。运算符当调用m2时,对str的引用被复制并传递给将其视为x的函数。运算符+创建一个新字符串,赋值x=x+"4"只是将x重定向到新字符串,而原始str变量保持不变。对吧?谢谢 最佳答案 String#+::str+other_str→new_strConcatenation—ReturnsanewStringcontainingother_strconc
我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat
这是我在ChefRecipe中的一blockRuby:#ifdatadirdoesn'texist,moveoverthedefaultoneif!File.exist?("/vol/postgres/data")execute"mv/var/lib/postgresql/9.1/main/vol/postgres/data"end结果是:Executingmv/var/lib/postgresql/9.1/main/vol/postgres/datamv:inter-devicemovefailed:`/var/lib/postgresql/9.1/main'to`/vol/post