Fortunately, as a good Unix system, Solaris supports easy daemon creation by encapsulating all the necessary steps into a single system function called daemon(3C). Thus the whole process of becoming a daemon is greatly simplified when compared to the traditional / legacy approach:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#include <cstdlib>
#include <cstdarg>
#include "toolbox.hxx"
void error( toolbox::log & log, const char * message )
{
int code = errno;
log.write( "ERROR: %s (%d)\n", message, code );
::exit( EXIT_FAILURE );
}
int main( )
{
toolbox::log log( "trace.log" );
if ( ! log.open() )
return EXIT_FAILURE;
log.write( "Starting up...\n" );
if ( ::daemon( 0, 0 ) < 0 )
error( log, "Couldn't become a daemon." );
log.write( "Successfully became a daemon!\n" );
::umask( 0 );
const int seconds = 30;
log.write( "Resting for %d seconds...\n", seconds );
::sleep( seconds );
log.write( "Bye cruel world!\n\n" );
log.close();
return EXIT_SUCCESS;
}
A typical log output could be similar to:
$ cat trace.log
[2017-05-12 16:29:11] Starting up...
[2017-05-12 16:29:11] Successfully became a daemon!
[2017-05-12 16:29:11] Resting for 30 seconds...
[2017-05-12 16:29:41] Bye cruel world!
It may be interesting to take a look under the hood at the system calls encapsulated by daemon(3C) in order to compare it with the traditional / legacy approach:
$ truss -f ./daemon-01
...
... getcwd("/...", 1024) = 0
... open("/.../trace.log", O_WRONLY|O_APPEND|O_CREAT, 0640) = 3
...
3155: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3155: write(3, " S t a r t i n g u p .".., 15) = 15
...
3155: forkx(0) = 3156
3155: _exit(0)
...
3156: forkx() (returning as child ...) = 3155
3156: getpid() = 3156 [3155]
...
3156: setsid() = 3156
...
3156: forkx(0) = 3158
3156: _exit(0)
...
3158: forkx() (returning as child ...) = 3156
3158: getpid() = 3158 [1]
...
3158: chdir("/") = 0
...
3158: open("/dev/null", O_RDWR) = 4
3158: fcntl(4, F_DUP2FD, 0x00000000) = 0
3158: fcntl(4, F_DUP2FD, 0x00000001) = 1
3158: fcntl(4, F_DUP2FD, 0x00000002) = 2
3158: close(4) = 0
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " S u c c e s s f u l l y".., 30) = 30
...
3158: umask(0) = 022
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " R e s t i n g f o r ".., 26) = 26
3158: nanosleep(...) (sleeping...)
3158: nanosleep(...) = 0
...
3158: write(3, " [ 2 0 1 7 - 0 5 - 1 2 ".., 22) = 22
3158: write(3, " B y e c r u e l w o".., 18) = 18
3158: close(3) = 0
...
3158: _exit(0)