您的execv() 代码有问题:
char *mArgv[MAXMOLES] = {"mole",snum};
execv(mArgv[0],mArgv );
参数列表需要以空指针终止:
char *mArgv[] = { "mole", snum, 0 };
execv(mArgv[0], mArgv);
此外,在处理程序代码(和主程序)中,您有:
char *snum;
sprintf(snum,"%d",num+1);
这是致命的;您需要为snum 分配空间。在这种情况下,修复很简单:
char snum[16];
sprintf(snum, "%d", num+1);
你可以使用:
char snum[16];
snprintf(snum, sizeof(snum), "%d", num+1);
但似乎没有必要。
另外一对相关的问题是:
- 因为你
cd到根目录,所以mole程序除非你在根目录中创建,否则不会被执行——这将是一件可恶的事情。
- 因为你
cd 到根目录,(如果它运行的话)mole 程序将尝试在根目录中创建它的日志文件——但它应该不能写入到根目录中的文件根目录。
您不应以用户root 运行测试代码或以root 开发。太危险了。
我观察到,虽然可以将一个精致的、生产就绪的守护进程放入后台,没有日志文件、标准输出和标准错误连接到/dev/null,但它使调试变得非常困难。由于很少有程序没有错误,您基本上应该始终将您的守护进程与标准输出和标准错误连接到日志文件(以附加模式打开,因此如果您截断日志文件,写入仍将发生在结束时现在截断的文件)。对于守护进程,您可能应该记录每条消息的时间,并且很可能还应该记录 PID。可以使用标准的日志功能包来自动执行此操作。如果没有日志文件,您将无法可靠地报告问题,因此您正在盲目运行,而盲目运行会导致您绊倒并受伤。
我不确定这些是唯一的问题,但它们可能足以解决您的大部分问题。
修改mole.c
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char **argv)
{
FILE *fp = fopen("/tmp/mole.log", "a");
if (fp != 0)
{
time_t now = time(0);
struct tm *utc = gmtime(&now);
char timestamp[32];
strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%SZ", utc);
char *s;
if (argc > 1 && strcmp(argv[1], "1") == 0)
s = "Pop mole1";
else
s = "Pop mole2";
fprintf(fp, "%s - %5d: %s\n", timestamp, (int)getpid(), s);
fclose(fp);
}
return 0;
}
这个程序和它的前身的主要区别在于它使用了一个固定的日志文件名,并且在日志文件中记录了时间和PID。
修改moletrap.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h> /* umask() */
#include <signal.h>
#include <unistd.h>
#include "stderr.h"
static pid_t pid_child_mole;
static int num;
// signal handler that kills child and forks a new one OR kills child
// and shuts down daemon
static void handler(int signum)
{
if (signum == SIGTERM)
{
err_remark("Send SIGTERM to %d\n", (int)pid_child_mole);
kill(pid_child_mole, SIGTERM);
err_remark("Exiting\n");
exit(0);
}
else if (signum == SIGUSR1)
{
if (num == 0 && pid_child_mole > 0)
{
err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
kill(pid_child_mole, SIGCHLD);
}
num = rand() % 2;
char snum[16];
sprintf(snum, "%d", num + 1);
char *mArgv[] = { "mole", snum, 0 };
pid_child_mole = fork();
if (pid_child_mole == 0)
{
err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
execv(mArgv[0], mArgv);
err_syserr("failed (1) to execute %s %s\n", mArgv[0], mArgv[1]);
}
(void) signal(SIGUSR1, handler);
}
else if (signum == SIGUSR2)
{
if (num == 1)
{
err_remark("Send SIGCHLD to %d\n", (int)pid_child_mole);
kill(pid_child_mole, SIGCHLD);
}
num = rand() % 2;
char snum[16];
sprintf(snum, "%d", num + 1);
char *mArgv[] = { "mole", snum, 0 };
pid_child_mole = fork();
if (pid_child_mole == 0)
{
err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
execv(mArgv[0], mArgv);
err_syserr("failed (2) to execute %s %s\n", mArgv[0], mArgv[1]);
}
(void) signal(SIGUSR2, handler);
}
else
err_remark("received unexpected signal %d\n", signum);
}
int main(int argc, char **argv)
{
const char *logfile = "/tmp/moletrap.log";
err_setarg0(argv[argc - argc]);
err_setlogopts(err_getlogopts() | ERR_STAMP | ERR_PID);
// Create child process
pid_t process_id = fork();
if (process_id < 0) // Indication of fork() failure
err_syserr("fork() failed\n");
if (process_id > 0)
{
// PARENT PROCESS exits successfully
printf("process ID of child process %d \n", process_id);
exit(0);
}
// unmask the file mode
umask(0);
// set new session
pid_t sid = setsid();
if (sid < 0)
err_syserr("setsid() failed\n");
// Change the current working directory to root.
// if (chdir("/") != 0)
// err_syserr("chdir() failed\n");
// Redirect standard input from /dev/null
close(STDIN_FILENO);
if (open("/dev/null", O_RDONLY) < 0)
err_syserr("failed to open /dev/null\n");
// Redirect standard output and standard error to a log file
int fd1 = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
if (fd1 < 0)
err_syserr("failed to open %s\n", logfile);
if (dup2(fd1, STDOUT_FILENO) < 0)
err_syserr("failed to send standard output to log file %s\n", logfile);
if (dup2(fd1, STDERR_FILENO) < 0)
err_syserr("failed to send standard error to log file %s\n", logfile);
close(fd1);
err_remark("Started\n");
(void) signal(SIGTERM, handler);
(void) signal(SIGUSR1, handler);
(void) signal(SIGUSR2, handler);
pid_child_mole = fork();
while (1)
{
sleep(1);
err_remark("Sleepers awake, salute ...\n");
if (pid_child_mole == 0)
{
int num = rand() % 2;
char snum[16];
sprintf(snum, "%d", num + 1);
char *mArgv[] = { "mole", snum, 0 };
err_remark("about to execute %s %s\n", mArgv[0], mArgv[1]);
execv(mArgv[0], mArgv );
err_syserr("failed (3) to execute %s %s\n", mArgv[0], mArgv[1]);
}
}
return(0);
}
此修订版使用原始信号处理代码、缺陷和所有内容。从理论上讲,它不应该做它在信号处理程序中所做的所有事情,但它可以“正常”工作。 OTOH,如果出现任何问题,除了重写代码之外别无他法。
代码使用我的"stderr.h" 标头并隐式实现stderr.c。这从根本上简化了这里的错误报告编码:err_syserr() 报告错误,系统错误消息基于errno 并退出,而err_remark() 写入消息并返回调用代码。 err_setarg0()函数记录程序名(常规以argv[0]为基础); err_getlogopts() 报告当前日志选项设置,err_setlogopts() 设置相同的值加上ERR_PID(记录每行输出的 PID)和ERR_STAMP(为每行输出添加时间戳)。标题为 150 行(93 行非空白,非注释行);源代码是 608 行(424 行非空白、非注释行)——太大了,无法在此处显示。如果您想要代码,请查看我的个人资料。
示例命令序列
$ ./moletrap # Reported 9424
$ kill -USR2 9424
$ kill -USR2 9424
$ kill -USR1 9424
$
$ ./moletrap # Reported 9456
$ kill -USR2 9456
$ kill -USR2 9456
$ kill -USR1 9456
$ kill -USR1 9456
$ kill -TERM 9456
$ kill -TERM 9456
$
$ ./moletrap # Reported 9499
$ kill -USR2 9499
$ kill -USR2 9499
$ kill -USR2 9499
$ kill -USR1 9499
$ kill -USR1 9499
$ kill -USR1 9499
$ kill -TERM 9499
$
样本mole.log
2014-11-20 05:28:49Z - 9425: Pop mole2
2014-11-20 05:29:12Z - 9428: Pop mole2
2014-11-20 05:33:36Z - 9457: Pop mole2
2014-11-20 05:34:00Z - 9462: Pop mole2
2014-11-20 05:34:02Z - 9463: Pop mole1
2014-11-20 05:36:54Z - 9500: Pop mole2
2014-11-20 05:37:07Z - 9501: Pop mole2
2014-11-20 05:37:08Z - 9504: Pop mole2
2014-11-20 05:37:09Z - 9505: Pop mole2
2014-11-20 05:37:13Z - 9506: Pop mole1
2014-11-20 05:37:14Z - 9507: Pop mole1
2014-11-20 05:37:15Z - 9508: Pop mole1
样本moletrap.log
moletrap: 2014-11-19 21:28:48 - pid=9424: Started
moletrap: 2014-11-19 21:28:49 - pid=9425: about to execute mole 2
moletrap: 2014-11-19 21:28:59 - pid=9426: about to execute mole 2
moletrap: 2014-11-19 21:28:59 - pid=9426: failed to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:29:02 - pid=9424: Send SIGCHLD to 9426
moletrap: 2014-11-19 21:29:02 - pid=9427: about to execute mole 2
moletrap: 2014-11-19 21:29:02 - pid=9427: failed to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:29:12 - pid=9428: about to execute mole 2
moletrap: 2014-11-19 21:33:35 - pid=9456: Started
moletrap: moletrap: 2014-11-19 21:33:36 - pid=9456: Sleepers awake, salute ...
2014-11-19 21:33:36 - pid=9457: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:36 - pid=9457: about to execute mole 2
moletrap: 2014-11-19 21:33:37 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:38 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:39 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:40 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:41 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:42 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:43 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:44 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:45 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:46 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:47 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:48 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:49 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:50 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:51 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:52 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:53 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:54 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:55 - pid=9460: about to execute mole 2
moletrap: 2014-11-19 21:33:55 - pid=9460: failed (2) to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:33:56 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:57 - pid=9456: Send SIGCHLD to 9460
moletrap: 2014-11-19 21:33:57 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:57 - pid=9461: about to execute mole 2
moletrap: 2014-11-19 21:33:57 - pid=9461: failed (2) to execute mole 2
error (14) Bad address
moletrap: 2014-11-19 21:33:58 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:33:59 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:00 - pid=9462: about to execute mole 2
moletrap: 2014-11-19 21:34:01 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:02 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:02 - pid=9463: about to execute mole 1
moletrap: 2014-11-19 21:34:03 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:04 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:05 - pid=9456: Sleepers awake, salute ...
moletrap: 2014-11-19 21:34:06 - pid=9456: Send SIGTERM to 9463
moletrap: 2014-11-19 21:34:06 - pid=9456: Exiting
moletrap: 2014-11-19 21:36:53 - pid=9499: Started
moletrap: moletrap: 2014-11-19 21:36:54 - pid=9499: Sleepers awake, salute ...
2014-11-19 21:36:54 - pid=9500: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:54 - pid=9500: about to execute mole 2
moletrap: 2014-11-19 21:36:55 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:56 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:57 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:58 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:36:59 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:00 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:01 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:02 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:03 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:04 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:05 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:06 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:07 - pid=9501: about to execute mole 2
moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:08 - pid=9499: Send SIGCHLD to 9501
moletrap: 2014-11-19 21:37:08 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:08 - pid=9504: about to execute mole 2
moletrap: 2014-11-19 21:37:09 - pid=9499: Send SIGCHLD to 9504
moletrap: 2014-11-19 21:37:09 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:09 - pid=9505: about to execute mole 2
moletrap: 2014-11-19 21:37:10 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:11 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:12 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:13 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:13 - pid=9506: about to execute mole 1
moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:14 - pid=9499: Send SIGCHLD to 9506
moletrap: 2014-11-19 21:37:14 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:14 - pid=9507: about to execute mole 1
moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:15 - pid=9499: Send SIGCHLD to 9507
moletrap: 2014-11-19 21:37:15 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:15 - pid=9508: about to execute mole 1
moletrap: 2014-11-19 21:37:16 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:17 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:18 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:19 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:20 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:21 - pid=9499: Sleepers awake, salute ...
moletrap: 2014-11-19 21:37:21 - pid=9499: Send SIGTERM to 9508
moletrap: 2014-11-19 21:37:21 - pid=9499: Exiting
'(24) Bad address' 错误是因为我只修复了使用execv() 的三个位置中的两个;修复第三个消除了错误。可以看到错误处理的发展;第一组没有确定哪个“执行失败”消息造成了麻烦;第二组显示它“执行失败(2)”,这使得看到问题变得微不足道。边看边学!
使用“睡眠者醒了,敬礼……”是一个(坏)笑话和混淆;它只是显示随着时间的推移循环的迭代。 (参见维基百科的Wachet auf 和Christians Awake, Salute the Happy Morn。)
这显示了您的代码在工作。我不相信 SIGCHLD 信号有任何相关性,但我把它们留在了里面。无论如何,孩子们很快就会死去,而不是因为被发送了 SIGCHLD。我还没有检查过僵尸——当心睡死人。