views:

65

answers:

3

Hi,

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've 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

+1  A: 

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).

caf
Changed to the _exit()added perror("accept"), i'm getting --> accept: Invalid argument
djTeller
I also debugged the accept function:new_fd = accept(sockfd,(struct sockaddr *)new_fd returns -1, and sockfd is always 4
djTeller
+3  A: 

May I direct you to existing library function daemon(3) to accomplish the same?

Nikolai N Fetissov
+2 if I could..
Tim Post
+3  A: 

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.

nos
+1 for looking at the actual problem.
Nikolai N Fetissov
This is exactly what happend, thank you very much.I debugged len before accept with and without the daemonize call.Without it it's positive, with it is negative, not sure why it happens, but setting len to the size of the address solved it!
djTeller