当线上程序发生段错误时,内核会把会发送SIGSEGV信号给程序,使程序中断,如果系统开启产生core dump功能,则系统会该程序的内存写入到core文件。不过大多数Linux发布版中,core dump是默认不开启的,可以使用命令ulimit -c来查看core file的大小限制以及配置开启core dump。
如果程序调用了seteuid()/setegid()改变 了进程的有效用户或组,即使开启core dump,该程序在段错误后系统默认不会生成对应的core文件。
以下有三种方式可以这类进程设置在段错误时生成core
1.设置ulimit -c以及suid_dumpable文件
这种方式简单粗暴,但是只对该终端执行的程序生效
设置core file大小限制为无限制
ulimit -c unlimited
将/proc/sys/fs/suid_dumpable文件的内容改为1(一般默认是0):
echo 1 > /proc/sys/fs/suid_dumpable
- 重启程序
- 如果想让修改永久生效,则需要在在配置文件加上
ulimit -c unlimited
,如 .bash_profile、/etc/profile或/etc/security/limits.conf
2.在程序中显示调用setrlimit以及prctl系统调用
setrlimit主要作用是设置core file限制为无限制
在执行setuid后显式prctl调用保证进程在段错误后也会生成core 文件
struct rlimit r;
r.rlim_cur=RLIM_INFINITY;
r.rlim_max=RLIM_INFINITY;
setrlimit (RLIMIT_CORE,&r);
......
setuid(user_id)
......
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)
3.通过gdb方式 attach进程后,对进程进行系统调用设置
这种方式只对运行的进程也生效,并且也不需要更改源程序代码,但不方便之处在于程序重新启动后无效
gdb -x core.cmd -p 进程号
core.cmd的内容
print "prctl(4, 1, 0, 0, 0)"
print prctl(4, 1, 0, 0, 0)
set $rlim = &{0ll, 0ll}
print "getrlimit(4, $rlim)"
print getrlimit(4, $rlim)
print *$rlim
set *$rlim[0] = -1
print "setrlimit(4, $rlim)"
print setrlimit(4, $rlim)
print "signal(6,(void (*) (int)) 0)"
print signal(6,(void (*) (int)) 0)
其实与第二点类似,都是通过系统调用方法来开启单个进程的core dump功能