我正在开发一个在Linux和Mac上工作的服务器应用程序。它是这样的:
启动控制器进程的主application
我可以使用几种方法(例如syslog或一个文件)进行日志记录,但现在我正在考虑syslog。有趣的是,除非我在下面的#ifdef部分中包含了#ifdef部分,否则在控制器进程中看不到syslog输出。
工作人员在Mac和linux中处理日志时完美无缺,不管是否使用下面的ifdef‘’ed部分。控制器还在Mac中记录得完美无缺,没有# ifdef‘’ed部分,但是在linux上,如果我想看到来自控制器进程的任何输出到syslog (或相应的日志文件),则需要ifdef。
那么,为什么呢?
static int
lock_down(void)
{
struct rlimit rl;
unsigned int n;
int fd0;
int fd1;
int fd2;
// Reset file mode mask
umask(0);
// change the working directory
if ((chdir("/")) < 0)
return EXIT_FAILURE;
// close any and all open file descriptors
if (getrlimit(RLIMIT_NOFILE, &rl))
return EXIT_FAILURE;
if (RLIM_INFINITY == rl.rlim_max)
rl.rlim_max = 1024;
for (n = 0; n < rl.rlim_max; n++) {
#ifdef __linux__
if (3 == n) // deep magic...
continue;
#endif
if (close(n) && (EBADF != errno))
return EXIT_FAILURE;
}
// attach file descriptors 0, 1 and 2 to /dev/null
fd0 = open("/dev/null", O_RDWR);
fd1 = dup2(fd0, 1);
fd2 = dup2(fd0, 2);
if (0 != fd0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}camh是近在咫尺的,但使用closelog()是成功的主意,所以这一荣誉属于吉利斯。不过,除了关闭syslog下的文件描述符之外,还必须继续进行其他一些工作。为了使代码正常工作,我在循环之前添加了一个对closelog()的调用:
closelog();
for (n = 0; n < rl.rlim_max; n++) {
if (close(n) && (EBADF != errno))
return EXIT_FAILURE;
}我依靠对手册页的逐字理解,说:
使用openlog()是可选的;它将由syslog()在必要时自动调用.
我将此解释为说,syslog将检测文件描述符是否在其下关闭。显然没有。需要在linux上使用一个显式的closelog()来告诉syslog描述符已关闭。
还有一件事仍然让我感到困惑:不使用closelog()可以阻止第一个分叉进程(控制器)甚至打开和使用日志文件。以下分叉进程可以使用syslog或日志文件,没有任何问题。也许在文件系统中存在一些缓存效应,使得第一个分叉进程有一个不可靠的“概念”,其中有哪些文件描述符可用,而下一组分叉进程被延迟到不受此影响吗?
发布于 2010-08-20 22:42:27
syslog(3)可能会使一个文件描述符保持syAdd.1-d的套接字打开;在它的脚下关闭它可能会导致问题。封闭(3)呼叫可能会有所帮助。
发布于 2010-08-20 22:42:53
文件描述符3的特殊方面是,它通常是分配新文件描述符的系统调用返回的第一个文件描述符,因为0、1和2通常设置为stdin、stdout和stderr。
这意味着,如果您调用的任何库函数为了执行其功能而为其内部目的分配文件描述符,它将得到fd 3。
openlog(3)库调用需要打开/dev/log才能与syslog守护进程通信。如果随后关闭所有文件描述符,则如果不以某种方式编写syslog库函数,则可能会中断它们。
发布于 2010-08-20 23:52:46
在Linux上调试此代码的方法是使用strace跟踪正在进行的实际系统调用;然后,对syslog使用文件描述符变得显而易见:
$ cat syslog_test.c
#include <stdio.h>
#include <syslog.h>
int main(void)
{
openlog("test", LOG_PID, LOG_LOCAL0);
syslog(LOG_ERR, "waaaaaah");
closelog();
return 0;
}
$ gcc -W -Wall -o syslog_test syslog_test.c
$ strace ./syslog_test
...
socket(PF_FILE, SOCK_DGRAM, 0) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
connect(3, {sa_family=AF_FILE, path="/dev/log"}, 16) = 0
send(3, "<131>Aug 21 00:47:52 test[24264]"..., 42, MSG_NOSIGNAL) = 42
close(3) = 0
exit_group(0) = ?
Process 24264 detachedhttps://stackoverflow.com/questions/3535282
复制相似问题