【问题标题】:Daemonize() issues on DebianDebian 上的 Daemonize() 问题
【发布时间】:2011-02-05 06:02:50
【问题描述】:

我目前正在为我的某个项目编写一个多进程客户端和一个多线程服务器。

服务器是一个守护进程。 为了实现这一点,我正在使用以下 daemonize() 代码:

static void daemonize(void)
{
    pid_t pid, sid;

    /* already a daemon */
    if ( getppid() == 1 ) return;

    /* Fork off the parent process */
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    /* At this point we are executing as the child process */

    /* Change the file mode mask */
    umask(0);

    /* Create a new SID for the child process */
    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE);
    }

    /* Change the current working directory.  This prevents the current
       directory from being locked; hence not being able to remove it. */
    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE);
    }

    /* Redirect standard files to /dev/null */
    freopen( "/dev/null", "r", stdin);
    freopen( "/dev/null", "w", stdout);
    freopen( "/dev/null", "w", stderr);
}

int main( int argc, char *argv[] ) {
    daemonize();

    /* Now we are a daemon -- do the work for which we were paid */
    return 0;
}

在 Debian (Ubuntu) 上测试服务器时,我有一个奇怪的副作用。

accept()函数总是无法接受连接,返回的pid是-1

我不知道是什么原因造成的,因为在 RedHat 和 CentOS 中它运行良好。

当我删除对 daemonize() 的调用时,Debian 上一切正常,当我重新添加它时,同样的 accept() 错误重现。

我一直在监控 /proc//fd,一切看起来都不错。

daemonize() 和 Debian 发行版中的某些内容似乎不起作用。 (Debian GNU/Linux 5.0,Linux 2.6.26-2-286 #1 SMP)

知道是什么原因造成的吗?

谢谢

【问题讨论】:

  • 在您的应用程序上运行 strace -f ,并包括从启动到第一个 accept() 失败的所有内容,希望这将包含一些线索。
  • 打印/记录errno 的值可能有助于更好地确定accept(2) 返回-1 的原因。

标签: c linux sockets posix daemon


【解决方案1】:

accept(2) 手册页说:

EINVAL 套接字没有监听 连接,或 addrlen 无效 (例如,是否定的)。

你可能有类似的东西

struct sockaddr_in;
socklen_t len;
...

new_fd = new_fd = accept(sockfd,(struct sockaddr *)&addr,&len);

但是,您需要将len设置为您传入的地址的大小:

struct sockaddr_in addr;
socklen_t len;
len = sizeof(addr);
...
new_fd = new_fd = accept(sockfd,(struct sockaddr *)&addr,&len);

因此,某些(不)幸运意味着您未初始化的“len”变量在某些情况下会得到一些无意义的值,并且接受失败,而它恰好在其他情况下工作。

【讨论】:

  • 这正是发生的事情,非常感谢。我在接受和不接受守护进程调用之前调试了 len 。没有它是积极的,它是消极的,不知道为什么会发生,但是将 len 设置为地址的大小解决了它!
【解决方案2】:

我可以指导您使用现有的库函数daemon(3) 来完成同样的任务吗?

【讨论】:

    【解决方案3】:

    这里,当父级退出时:

    /* If we got a good PID, then we can exit the parent process. */
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }
    

    你应该打电话给_exit(),而不是exit()。 (我不确定这是否会导致您的问题,但有可能)。

    accept() 返回 -1 时,errno 设置为什么? (您可以在那里的代码中输入perror("accept");)。

    【讨论】:

    • 更改为 _exit() 添加了 perror("accept"),我得到了 --> 接受:无效参数
    • 我还调试了accept函数:new_fd = accept(sockfd,(struct sockaddr *)&addr,&len); new_fd 返回 -1,sockfd 始终为 4
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 2021-12-15
    • 2020-09-24
    • 2023-01-29
    • 2016-01-20
    • 2017-07-26
    相关资源
    最近更新 更多