本文介绍 pppd
对信号 SIGTERM
的处理,以及错误方式关闭 pppd 带来的问题
现象
GPRS
模块正常工作之后需要关闭来使用串口 /dev/ttyS0
,此时串口工作不正常
关闭方式为
kill -9 pppd call wcdma
解决方案
将关闭方式修改为 pppd
提供的 ppp-off
#!/bin/sh
######################################################################
#
# Determine the device to be terminated.
#
if [ "$1" = "" ]; then
DEVICE=ppp0
else
DEVICE=$1
fi
######################################################################
#
# If the ppp0 pid file is present then the program is running. Stop it.
if [ -r /var/run/$DEVICE.pid ]; then
kill -INT `cat /var/run/$DEVICE.pid`
#
# If the kill did not work then there is no process running for this
# pid. It may also mean that the lock file will be left. You may wish
# to delete the lock file at the same time.
if [ ! "$?" = "0" ]; then
rm -f /var/run/$DEVICE.pid
echo "ERROR: Removed stale pid file"
exit 1
fi
#
# Success. Let pppd clean up its own junk.
echo "PPP link to $DEVICE terminated."
exit 0
fi
#
# The ppp process is not running for ppp0
echo "ERROR: PPP link is not active on $DEVICE"
exit 1
分析
kill
发送的信号存在差异 SIGKILL
或 SIGTERM
man pppd
得到如下信息:
SIGINT, SIGTERM
These signals cause pppd to terminate the link (by closing LCP), restore the serial device settings, and exit. If a connector or disconnector process is currently
running, pppd will send the same signal to its process group, so as to terminate the connector or disconnector process.
因此需要使用 kill
来发送信号 SIGTERM
来完成回收操作
sourcecode
static void setup_signals()
{
struct sigaction sa;
/*
* Compute mask of all interesting signals and install signal handlers
* for each. Only one signal handler may be active at a time. Therefore,
* all other signals should be masked when any handler is executing.
*/
sigemptyset(&signals_handled);
sigaddset(&signals_handled, SIGHUP);
sigaddset(&signals_handled, SIGINT);
sigaddset(&signals_handled, SIGTERM);
sigaddset(&signals_handled, SIGCHLD);
sigaddset(&signals_handled, SIGUSR2);
#define SIGNAL(s, handler) do { \
sa.sa_handler = handler; \
if (sigaction(s, &sa, NULL) < 0) \
fatal("Couldn't establish signal handler (%d): %m", s); \
} while (0)
sa.sa_mask = signals_handled;
sa.sa_flags = 0;
SIGNAL(SIGHUP, hup); /* Hangup */
SIGNAL(SIGINT, term); /* Interrupt */
SIGNAL(SIGTERM, term); /* Terminate */
SIGNAL(SIGCHLD, chld);
SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */
SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */
...
}
/*
* term - Catch SIGTERM signal and SIGINT signal (^C/del).
*
* Indicates that we should initiate a graceful disconnect and exit.
*/
/*ARGSUSED*/
static void
term(sig)
int sig;
{
/* can't log a message here, it can deadlock */
got_sigterm = sig;
if (conn_running)
/* Send the signal to the [dis]connector process(es) also */
kill_my_pg(sig);
notify(sigreceived, sig);
if (waiting)
siglongjmp(sigjmp, 1);
}
最终通过 asked_to_quit
完成
if (asked_to_quit) {
bundle_terminating = 1;
if (phase == PHASE_MASTER)
mp_bundle_terminated();
}