![进程在关闭时阻塞](https://linux22.com/image/92337/%E8%BF%9B%E7%A8%8B%E5%9C%A8%E5%85%B3%E9%97%AD%E6%97%B6%E9%98%BB%E5%A1%9E.png)
我正在开发一个运行 Debian Wheezy 的系统,其应用程序作为其正常行为的一部分会生成一些子进程。在大多数情况下,当父应用程序被终止时,它会清除所有子应用程序,然后退出。但是,当我关闭/重新启动计算机时,计算机经常会在关闭前挂起几分钟。该机器是远程/无头的,所以我从我的一端看到的是一条系统正在关闭的消息,然后我的 ssh 会话将被终止,然后当我尝试登录时,我将在接下来的几分钟内收到连接被拒绝的错误当我浏览 /var/log/syslog 时,我会看到如下条目:
[ 3840.402493] INFO: task child_process:4455 blocked for more than 120 seconds. [ 3840.402579] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 3840.402684] child_process D c109bbf8 0 4455 3702 0x00000000 [ 3840.402691] f79c7b00 00000046 00000001 c109bbf8 f0bed5b0 333f9aaa 00000351 c1483b00 [ 3840.402703] c1483b00 00000292 c109bcf9 00000292 00000000 f2c005a0 00000000 edd1fd34 [ 3840.402714] 00000292 c109bebf c10abe25 00000001 f2bd4740 00000000 00000001 c109bc0a [ 3840.402726] Call Trace: [ 3840.402733] [] ? free_pages_prepare+0xc0/0xf1 [ 3840.402741] [] ? free_hot_cold_page+0x3d/0xf7 [ 3840.402749] [] ? __pagevec_free+0x3e/0x55 [ 3840.402756] [] ? page_address+0x1b/0x85 [ 3840.402763] [] ? free_pages_prepare+0xd2/0xf1 [ 3840.402771] [] ? __mutex_lock_common.isra.6+0x11d/0x132 [ 3840.402778] [] ? mutex_lock+0x15/0x21 [ 3840.402785] [] ? tty_release+0x3d/0x400 [ 3840.402794] [] ? ip_mc_del_src+0xf1/0x12e [ 3840.402801] [] ? ip_mc_leave_src+0x22/0x68 [ 3840.402809] [] ? kmem_cache_free+0x23/0x55 [ 3840.402816] [] ? fput+0xd7/0x161 [ 3840.402822] [] ? filp_close+0x54/0x5a [ 3840.402828] [] ? put_files_struct+0x4b/0x88 [ 3840.402834] [] ? do_exit+0x237/0x60d [ 3840.402842] [] ? recalc_sigpending+0xf/0x2f [ 3840.402849] [] ? dequeue_signal+0xb4/0x126 [ 3840.402855] [] ? do_group_exit+0x56/0x83 [ 3840.402863] [] ? get_signal_to_deliver+0x43b/0x465 [ 3840.402871] [] ? do_signal+0x32/0x52c [ 3840.402879] [] ? update_rmtp+0x45/0x45 [ 3840.402886] [] ? do_futex+0x99/0x6c6 [ 3840.402893] [] ? read_tsc+0xa/0x28 [ 3840.402901] [] ? timekeeping_get_ns+0x10/0x47 [ 3840.402907] [] ? sys_futex+0xbb/0x10f [ 3840.402915] [] ? do_notify_resume+0x1e/0x5c [ 3840.402922] [] ? work_notifysig+0x13/0x1b [ 3840.402929] [] ? start_cpu_timer+0x39/0x62 [ 3840.402935] [] ? vmstat_cpuup_callback+0x18/0x5a
对于发出重新引导请求之后但在系统实际关闭之前的许多子进程。
可能相关的是,有时父应用程序退出后会让子应用程序继续运行。为了便于手动终止这些进程,我有一个脚本,基本上包括:
#!/bin/bash
killall -q parent_process
killall -q child_1
killall -q child_2
#etc...
手动运行时,此脚本可靠地杀死所有进程并且永远不会挂起。此外,如果手动启动子进程,则不会挂起/表现出此行为。
我的直觉告诉我,问题在于父应用程序没有正确清理它的子进程,但不幸的是,父进程是一个专有的内部应用程序,我无法更改其实现,所以我一直在尝试找到解决方法。如果我在关闭/重新启动之前手动运行我的killall脚本,则关闭永远不会延迟,所以我一直在尝试找到一种方法来让该脚本在关闭/重新启动时运行
我的第一次尝试是将 Killall 脚本复制到 /etc/init.d 中,然后将其作为 K01killstuff 链接到 rc0.d 和 rc6.d 中,但这不起作用,所以我决定尝试编写一个正确的 init 脚本。我从 /etc/init.d 中的框架开始,得出:
#! /bin/sh
### BEGIN INIT INFO
# Provides: killstuff
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Stop: 0 1 6
# Short-Description: Stop applications
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO
# Author:
#
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="Description of the service"
NAME=daemonexecutablename
DAEMON=/usr/sbin/$NAME
DAEMON_ARGS="--options args"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that stops the daemon/service
#
do_stop()
{
killall -q parent_process
killall -q child_1
killall -q child_2
}
case "$1" in
start)
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping Applications"
do_stop
;;
status)
;;
restart|force-reload)
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:
我测试了脚本/etc/init.d/killstuff stop
并确认它确实杀死了我期望的所有进程,然后运行update-rc.d killstuff defaults
,并看到在 rc0.d 和 rc6.d 中创建了链接,但系统在重新启动时仍然挂起。这让我相信这些进程需要在关闭序列中尽早终止
那么我还可以在哪些地方尝试调用我的终止脚本呢?或者,除了在系统关闭之前杀死所有应用程序以尝试使系统关闭更顺利之外,我还可以尝试其他方法吗?