void daemon_t::_grandchild( pipe_t & c_pipe, pipe_t & g_pipe ) { try { c_pipe.writer().close(); _init(); // Initialization finished successfully -- let parent know everything is ok. g_pipe.writer().write( ok ); g_pipe.writer().close(); } catch ( std::exception const & ex ) { g_pipe.writer().write( string_t( ex.what() ) + "\n" ); throw; } catch ( ... ) { g_pipe.writer().write( "Unknown exception occurred\n" ); throw; }; // try _body(); }; // _grandchild
void daemon_t::_child( pipe_t & c_pipe, pipe_t & g_pipe ) { try { int error = -1; c_pipe.reader().close(); g_pipe.reader().close(); // Reopen standard streams. // Associate all the standard streams with `/dev/null'. file_t null( * this ); null.open( "/dev/null", O_RDONLY, 0 ); error = dup2( null.fd(), STDIN_FILENO ); SYSERR( error < 0, "dup2", "Reopening stdin" ); null.close(); null.open( "/dev/null", O_WRONLY, 0 ); error = dup2( null.fd(), STDOUT_FILENO ); SYSERR( error < 0, "dup2", "Reopening stdout" ); error = dup2( null.fd(), STDERR_FILENO ); SYSERR( error < 0, "dup2", "Reopening stderr" ); null.close(); pid_t sid = 0; ESYSCALL( "creating session", "setsid", sid = setsid(), sid > 0, "session " << sid << " created" ); // Ignore unused signals. // We ignore signals in child so in grandchild these signals are fro the very beginning. // If daemon need any of these signals, it will handle them explicitly. thread_t::ignore_signal( SIGHUP ); thread_t::ignore_signal( SIGINT ); thread_t::ignore_signal( SIGQUIT ); thread_t::ignore_signal( SIGUSR1 ); thread_t::ignore_signal( SIGUSR2 ); thread_t::ignore_signal( SIGTERM ); thread_t::ignore_signal( SIGCHLD ); thread_t::ignore_signal( SIGTTIN ); thread_t::ignore_signal( SIGTTOU ); thread_t::ignore_signal( SIGWINCH ); pid_t pid = 0; ESYSCALL( "forking grandchild process", "fork", pid = fork(), pid >= 0, "grandchild process forked " << ( pid == 0 ? "(i am grandchild)" : "(i am child)" ) ); if ( pid == 0 ) { _grandchild( c_pipe, g_pipe ); return; // TODO: or exit? }; // if g_pipe.writer().close(); ESYSCALL( "anti-zombying grandchild", "waitpid", error = waitpid( pid, NULL, WNOHANG ), error != -1, "grandchild anti-zombied" ); // We cannot just close pipe: on the parent end ir will be not clear if everything is ok // or child silently died. So let us write `ok' to the pipe -- parent will know that we // are really ok. c_pipe.writer().write( ok ); } catch ( std::exception const & ex ) { c_pipe.writer().write( string_t( ex.what() ) + "\n" ); } catch ( ... ) { c_pipe.writer().write( "Unknown exception occurred\n" ); }; // try c_pipe.writer().close(); }; // _child