I'm currently writing a multi-process client and a multi-treaded server for some project i have.
The server is a Daemon. In order to accomplish that, i'm using the following daemonize() code:
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;
}
I have a strange side effect when testing the server on Debian (Ubuntu).
The accept() function always fail to accept connections, the pid returned is -1
I have no idea what causing this, since in RedHat & CentOS it works well.
When i remove the call to daemonize(), everything works well on Debian, when i add it back, same accept() error reproduce.
I'v开发者_如何学Pythone been monitring the /proc//fd, everything looks good.
Something in the daemonize() and the Debian release just doesn't seem to work. (Debian GNU/Linux 5.0, Linux 2.6.26-2-286 #1 SMP)
Any idea what causing this?
Thank you
The accept(2) manpage says:
EINVAL Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
Likely you have something like
struct sockaddr_in;
socklen_t len;
...
new_fd = new_fd = accept(sockfd,(struct sockaddr *)&addr,&len);
However, you need to set len
to the size of the address you pass in:
struct sockaddr_in addr;
socklen_t len;
len = sizeof(addr);
...
new_fd = new_fd = accept(sockfd,(struct sockaddr *)&addr,&len);
So, by some (un)lucky means your uninitialized 'len' variable get some nonsense value in some cases, and accept fails, while it happens to work in other scenarios.
May I direct you to existing library function daemon(3)
to accomplish the same?
Here, when the parent exits:
/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
You should be calling _exit()
, not exit()
. (I am not certain that this is causing your problem, but it's possible).
What is errno
set to when accept()
returns -1? (You could put a perror("accept");
in the code there).
精彩评论