tags:

views:

109

answers:

2

I'm running a running a simple daemon test in c++. It runs fine without the sleep() but if I add sleep() func it runs once then stays a sleep. Further the first run should print once "Hello" in logs/log.dat file but that doesn't happen either. Here is the code:

 #include <cstdlib>  
 #include <cstdio>  
 #include <iostream>  
 #include <unistd.h>  
 using namespace std;  
 int main(int argc, char** argv) {  
    FILE *f = NULL;   
    if ((f = fopen("logs/log.dat  ", "w")) != NULL) {  
        if (daemon(0, 0) >= 0) {  
            while (true) {  
                fprintf(f, "%s\n", "Hello");  
                sleep(5);  
            }  
        } else {  
            fprintf(f, "%s\n", "Error detaching terminal");  
        }  
    } else {  
        printf("%s\n", "Cannot open log file");  
    }  
    return 0;  
}
+3  A: 

Try adding fflush() after your fprintf(). It might be working but just has not written the data to the disk yet.

Jay
Also closing the file before ending the program is good form.
Greg Domjan
@Greg: the program doesn't terminate.
Jonathan Leffler
A: 

What is in the daemon() function? In particular, does it close open files other than standard input, standard output and standard error? If so, then the subsequent fprintf() statements fail because the file that was opened before you called daemon() is closed afterwards.

If your code tested the return values from the printing functions, you would be able to find this out (though you'd probably have to open a log file with an absolute pathname to be able to report it from the daemonized process).

The quickest way to check this hypothesis may be to open the log file after daemonizing.

Note that some daemon() routines change directory too - typically to the root directory. That would give you a headache with the relative path to the log file.


On MacOS X, the daemon(3) function is provided with a declaration in <stdlib.h>; it was introduced in BSD 4.4, it seems:

SYNOPSIS

#include <stdlib.h>

 int
 daemon(int nochdir, int noclose);

DESCRIPTION

The daemon() function is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons. [...]

Unless the argument nochdir is non-zero, daemon() changes the current working directory to the root (/).

Unless the argument noclose is non-zero, daemon() will redirect standard input, standard output, and standard error to /dev/null.


You can inspect the FreeBSD 8 source code.

Since the call to daemon() passes 0 twice, the code does do a chdir("/") and it reconnects file descriptors 0, 1, 2 to '/dev/null'. The manual page goes on to discuss fork(2) and setsid(2). So, we can be moderately confident that your program has its standard I/O channels reconnected to /dev/null, and the current directory changed to the root directory.

The man page does mention that you should be careful to ensure that any opened files have a file descriptor greater than 2 to avoid issues. Can you print 'fileno(f)' somewhere - it is an integer - and ensure that it is greater than 2. If it is not big enough, then that is the cause of your trouble; don't invoke your program with any of stdin, stdout or stderr already closed.

That doesn't yet explain the absence of data from the file, nor why sleep() affects the result. Of course, the classic implementation of sleep() fiddles with signals and SIGALRM; the man page for daemon(3) mentions SIGHUP. However, the FreeBSD 8 implementation of sleep(3) uses the nanosleep(2) system call.

So, I'm going to agree with Jay's suggestion - the file will be fully buffered and you have to wait for a large number of 5-second cycles to print enough data to flush the buffer (that might need 4096 bytes, at 6 bytes per 5 seconds, will require about an hour to produce anything in the file). Adding fflush() is most likely to fix the 'non-appearance of message' issue. Alternatively, use setvbuf(f, 0, _IONBF, 0); to turn off all buffering, or setvbuf(f, 0, _IOLBF, BUFSIZ); to enable line buffering. And sleep() is a factor simply because it slows the processing down so much.

Jonathan Leffler