问题现象

大量僵尸进程


root 32278 0.0 0.0 0 0 ? Z 05:39 0:00 [runuser] <defunct>
root 32280 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32304 0.0 0.0 0 0 ? Z Aug21 0:00 [runuser] <defunct>
root 32362 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32448 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32475 0.0 0.0 0 0 ? Z Aug20 0:00 [runuser] <defunct>
root 32498 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32509 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>
root 32551 0.0 0.0 0 0 ? Z 09:54 0:00 [runuser] <defunct>
root 32556 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>
root 32557 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>
root 32611 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32612 0.0 0.0 0 0 ? Z Aug22 0:00 [runuser] <defunct>
root 32647 0.0 0.0 0 0 ? Z Aug19 0:00 [runuser] <defunct>
root 32699 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>
root 32700 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>
root 32716 0.0 0.0 0 0 ? Z Aug19 0:00 [runuser] <defunct>
root 32753 0.0 0.0 0 0 ? Z Aug18 0:00 [runuser] <defunct>

systemd crash


#pstack 1
#0 0x00007fba436a4a2d in pause () from /lib64/libpthread.so.0
#1 0x00007fba44c66ecd in freeze ()
#2 0x00007fba44c14eef in crash.2986 ()
#3 <signal handler called>
#4 0x00007fba433095f7 in raise () from /lib64/libc.so.6
#5 0x00007fba4330ace8 in abort () from /lib64/libc.so.6
#6 0x00007fba44c85c72 in log_assert_failed ()
#7 0x00007fba44c4635d in unit_watch_pid ()
#8 0x00007fba44be3767 in service_spawn.9373 ()
#9 0x00007fba44c5ecab in service_start.9527 ()
#10 0x00007fba44bdc1ba in manager_dispatch_run_queue.3886 ()
#11 0x00007fba44c37db2 in source_dispatch.52334.3984 ()
#12 0x00007fba44c3adba in sd_event_dispatch ()
#13 0x00007fba44c0c9ef in manager_loop ()
#14 0x00007fba44bcb86c in main ()
(gdb)
(gdb) bt
#0 0x00007fba436a4a2d in pause () from /lib64/libpthread.so.0
#1 0x00007fba44c66ecd in freeze () at src/shared/util.c:3833
#2 0x00007fba44c14eef in crash.2986 (sig=<optimized out>) at src/core/main.c:223
#3 <signal handler called>
#4 0x00007fba433095f7 in raise () from /lib64/libc.so.6
#5 0x00007fba4330ace8 in abort () from /lib64/libc.so.6
#6 0x00007fba44c85c72 in log_assert_failed (text=<optimized out>, file=<optimized out>, line=<optimized out>, func=<optimized out>) at src/shared/log.c:753
#7 0x00007fba44c4635d in unit_watch_pid (u=0x7fba44e44250, pid=0) at src/core/unit.c:2017
#8 0x00007fba44be3767 in service_spawn.9373 (s=0x7fba44e44250, c=0x7fba68f07ad0, timeout=90000000, pass_fds=<optimized out>, apply_permissions=<optimized out>, apply_chroot=<optimized out>,
apply_tty_stdin=true, is_control=true, _pid=0x7fba44e4486c) at src/core/service.c:1170
#9 0x00007fba44c5ecab in service_enter_start_pre (s=0x7fba44e44250) at src/core/service.c:1596
#10 service_start.9527 (u=0x7fba44e44250) at src/core/service.c:1841
#11 0x00007fba44bdc1ba in manager_dispatch_run_queue.3886 (source=<optimized out>, userdata=0x7fba44d132e0) at src/core/unit.c:1481
#12 0x00007fba44c37db2 in source_dispatch (s=s@entry=0x7fba44d11ea0) at src/libsystemd/sd-event/sd-event.c:2155
#13 0x00007fba44c3adba in sd_event_dispatch (e=0x7fba44d11c30) at src/libsystemd/sd-event/sd-event.c:2472
#14 0x00007fba44c0c9ef in sd_event_run (timeout=18446744073709551615, e=0x7fba44d11c30) at src/libsystemd/sd-event/sd-event.c:2501
#15 manager_loop (m=0x7fba44d132e0) at src/core/manager.c:2070
#16 0x00007fba44bcb86c in main (argc=5, argv=0x7ffc45ee3a38) at src/core/main.c:1755
(gdb)

问题代码定位

(gdb) list unit_watch_pid
2008
2009 unit_add_to_dbus_queue(u);
2010 unit_add_to_gc_queue(u);
2011 }
2012
2013 int unit_watch_pid(Unit *u, pid_t pid) {
2014 int q, r;
2015
2016 assert(u);
2017 assert(pid >= 1); # 这里触发
(gdb)
(gdb) list src/core/service.c:1170
return r;
static int service_load_pid_file(Service *s, bool may_warn) { 1165 s->exec_runtime,
1166 &pid);
1167 if (r < 0)
1168 goto fail;
1169
1170 r = unit_watch_pid(UNIT(s), pid); # 这里调用
1171 if (r < 0)
1172 /* FIXME: we need to do something here */
1173 goto fail;
1174
(gdb) list src/core/service.c:1596
static void service_enter_start_pre(Service *s) { 1591 * be left from previous runs. */
1592 service_kill_control_processes(s);
1593
1594 s->control_command_id = SERVICE_EXEC_START_PRE;
1595
1596 r = service_spawn(s,
1597 s->control_command,
1598 s->timeout_start_usec,
1599 false,
1600 !s->permissions_start_only

复现方法

  1. 创建一个vm中测试
  2. 想办法耗尽内存
# mount -t tmpfs -o size=20G tmpfs /mnt
# dd if=/dev/zero of=/mnt/file bs=1M
  1. while :; do systemctl restart iptables.service; sleep 5; done

分析

问题发生在当系统内存耗尽,恰好在此时,有个systemd的service重启,此时,systemd需要分配一个pid,但是因为内存耗尽,无法分配pid。然后触发了systemd一个bug:

BUG存在于: 创建pid函数exec_spawn(), 当创建pid失败的时候,理应返回错误值,但是这里返回的是0。 这个0是r决定的。 这个r是r = exec_context_load_environment() 函数的返回值,然而这个函数永远都是返回成功,导致,pid < 0 pid创建失败后,依然返回0

创建pid函数exec_spawn():
int exec_spawn
pid = fork();
if (pid < 0)
return log_unit_error_errno(params->unit_id, r, "Failed to fork: %m");

service重启,systemd会为service创建一个pid,在pid<0 的情况下,执行到unit_watch_pid() 函数,unit_watch_pid()函数判断assert(pid >= 1);

service_spawn()函数-> 调用exec_spawn()
重启service 会调用service_spawn()函数 static int service_spawn(...
r = exec_spawn(c,
&s->exec_context,
&exec_params,
s->exec_runtime,
&pid);
if (r < 0)
goto fail; r = unit_watch_pid(UNIT(s), pid);
if (r < 0)
/* FIXME: we need to do something here */
goto fail; *_pid = pid;
int unit_watch_pid(Unit *u, pid_t pid) {
int q, r; assert(u);
assert(pid >= 1);

REF

patch:

https://github.com/lnykryn/systemd-rhel/pull/119/commits/e18a5fa348aae0800807c3121a1ccf750eca206f

https://github.com/systemd/systemd/pull/5886

solution:

https://access.redhat.com/solutions/3096191

systemd bug: bz1437114 core:execute: fix fork() fail handling in exec_spawn()的更多相关文章

  1. electron-vue在npm run build时报错 ⨯ cannot execute cause=fork/exec C:\Users\801\AppData\Local\electron-builder\Cache\winCodeSign\winCodeSign-2.5.0\rcedit-ia32.exe: Access is denied.

    问题描述 在electron-vue执行npm run build时报错,错误如下: ⨯ cannot execute cause=fork/exec C:\Users\801\AppData\Loc ...

  2. 缺陷的背后(四)---多进程之for循环下fork子进程引发bug

    导语 业务模块为实现高并发时的更快的处理速度,经常会采用多进程的方式去处理业务.多进程模式下常见的三种bug:for循环下fork子进程导致产生无数孙子进程,僵尸进程,接口窜包.本章主要介绍第一种常见 ...

  3. MyCat不支持毫秒 bug fix

    问题描述:mysql jdbc的驱动(mysql-connector-java-5.1.34.jar)设置的服务器的版本号最低是5.6.4才不会截取时间毫秒,但是现在取的是mycat 的版本号 5.5 ...

  4. Java Concurrency - Fork/Join Framework

    Normally, when you implement a simple, concurrent Java application, you implement some Runnable obje ...

  5. [原]CentOS7.2最小安装环境部署Asp.NET Core笔记

    转载请注明原作者(think8848)和出处(http://think8848.cnblogs.com) 写在前面的话 不知不觉在cnblogs上注册已经10多年了,看我的园龄就直接暴露了我实际年龄, ...

  6. atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug

    atitit.java给属性赋值方法总结and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId&qu ...

  7. 给MySQL官方提交的bug report备忘

    1.  Bug #72215 When LOCK_plugin conflicts very much, one uninstall-audit-plugin operation crash  htt ...

  8. git Bug分支

    Bug分支 软件开发中,bug就像家常便饭一样.有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除. 当你接 ...

  9. atitit.java方法属性赋值and BeanUtils 1.6.1 .copyProperty的bug

    atitit.java分配给属性值方法and BeanUtils 1.6.1 .copyProperty的bug 1. core.setProperty(o, "materialId&quo ...

随机推荐

  1. 【airtest】报错:requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer')),解决方法如下

    1. 环境及设备:mac, xcode , iphonex 2. 最近出现一个让人费解的问题,airtest 没跑多长时间,服务就断掉,而且总是报“requests.exceptions.Connec ...

  2. vue学习笔记——脚手架安装

    项目启动:npm run build 脚手架 vue cli vue cli --2 安装命令 #全局安装 npm install --global vue-cli #卸载vue-cli  npm u ...

  3. CentOS 7 yum 安装redis(更简单)

    一.安装redis 1.检查是否有redis yum 源 1 yum install redis 2.下载fedora的epel仓库 1 yum install epel-release 3.安装re ...

  4. jmeter搭建

    jdk 1.8的地址  链接:https://pan.baidu.com/s/1eEyYbzo1Tfbvbmf_vN2yUA 密码:6dxi 1.安装JDK 选择安装目录 安装过程中会出现两次 安装提 ...

  5. 训练1-D

    把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果.在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果. Input 每行包含 ...

  6. 《代码敲不队》第八次团队作业:Alpha冲刺 第五天

    项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 代码敲不队 作业学习目标 掌握软件编码实现的工程要求. 团队项目github仓库地址链接 GitH ...

  7. Mysql 索引-1

    索引的类型 根据数据库的功能,可以在数据库设计器中创建四种索引:唯一索引.非唯一索引.主键索引和聚集索引. 索引的不同应用场景 场景 1. 当数据多且字段值有相同的值得时候用普通索引. 2. 当字段多 ...

  8. BA-siemens-insight_lenum点

    lenum点特性 lenum点有如下特点 如果状态字是自定义的,只能在bacnet / ip的aln层使用 如果想在ms/tp层使用lenum的功能,就必须将system profile中bacnet ...

  9. Android仿IOS的AssistiveTouch的控件EasyTouch实现

    概述: 之前我听到过一则新闻,就是说Ipone中的AssistiveTouch的设计初衷是给残疾人使用的. 而这一功能在亚洲(中国)的使用最为频繁. 虽不知道这新闻的可靠性,但无庸置疑的是它的确给我们 ...

  10. 稀疏编码(Sparse Coding)的前世今生(二)

    为了更进一步的清晰理解大脑皮层对信号编码的工作机制(策略),须要把他们转成数学语言,由于数学语言作为一种严谨的语言,能够利用它推导出期望和要寻找的程式.本节就使用概率推理(bayes views)的方 ...