Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Omniifr::DaemonImpl Class Reference

Utility class that contains various methods for running omniIFR as a Unix daemon. More...

#include <daemon_unix.h>

Collaboration diagram for Omniifr::DaemonImpl:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 DaemonImpl ()
 ~DaemonImpl ()
void tracefile (const char *val)
 Set _tracefile.
void pidfile (const char *val)
 Set _pidfile.
void foreground (bool val)
 Set _foreground.
void initialize (int &, char **&)
 Does nothing on Unix.
void daemonize ()
 Puts the current process into the background.
void runningOk ()
 Called to signal that all startup operations have completed OK.
void shutdown (int status)
 Exit handler called (indirectly) by ::on_exit() - shuts down the daemon.

Static Public Member Functions

static void log (const char *message)
 Callback, used as a parameter to omniORB::setLogFunction().

Public Attributes

char * _tracefile
 The tracefile name (if any).
bool _foreground
 TRUE for debug mode (run in foreground).
char * _pidfile
 The pidfile name (if any).
int _pipe [2]
 Unnamed pipe for child->parent comms.
bool _havePidfile
 Is there a pidfile for us to clean up?
bool _haveParent
 Is there a parent for us to clean up?
bool _haveSyslog
 Should we close syslog before quitting?

Static Public Attributes

static DaemonImpl _inst

Private Member Functions

void fork ()
 Performs the actual fork.
void redirectStreamsTo (const char *filename)
 Redirect stdout & stderr to filename.
int openFileFor (int fd, const char *filename, int flags)
 Opens a (new?) file called 'filename' for writing, and uses it to hijack stream 'fd'.
void checkPidfileOrShutdown ()
 If pidfile exists & contains a running process then shutdown() (Unix).
void writePidfile ()
int waitForChild ()
 Called by the parent process (Unix).
void notifyParent (int status)
 Tells the parent to exit with the given status (Unix).

Detailed Description

Utility class that contains various methods for running omniIFR as a Unix daemon.

Features: pidfile support, forking, redirect omniORB trace to syslog (or tracefile).

Definition at line 37 of file daemon_unix.h.


Constructor & Destructor Documentation

Omniifr::DaemonImpl::DaemonImpl  ) 
 

Definition at line 119 of file daemon_unix.cc.

00119 {}

Omniifr::DaemonImpl::~DaemonImpl  ) 
 

Definition at line 122 of file daemon_unix.cc.

References _pidfile, and _tracefile.

00123 {
00124   delete[] _pidfile;
00125   delete[] _tracefile;
00126   _pidfile=NULL;
00127   _tracefile=NULL;
00128 }


Member Function Documentation

void Omniifr::DaemonImpl::checkPidfileOrShutdown  )  [private]
 

If pidfile exists & contains a running process then shutdown() (Unix).

Also shuts down if pidfile is inaccessible.

Definition at line 283 of file daemon_unix.cc.

References _pidfile, and STRERR_FILE_LINE.

Referenced by daemonize().

00284 {
00285   if(!_pidfile)
00286       return;
00287 
00288   // Try to read pidfile.
00289   pid_t pidFromFile =0;
00290   struct stat buf;
00291   if(0==::stat(_pidfile,&buf))
00292   {
00293     if(!S_ISREG(buf.st_mode))
00294     {
00295       cerr<<"Pidfile '"<<_pidfile<<"' is not a regular file."<<endl;
00296       ::exit(-1);
00297     }
00298     try
00299     {
00300       ifstream infile(_pidfile);
00301       infile>>pidFromFile;
00302       infile.close();
00303     }
00304     catch(...)
00305     {
00306       cerr<<"Failed to read pidfile'"<<_pidfile<<"'."<<endl;
00307       ::exit(-1);
00308     }
00309   }
00310   else if(errno!=ENOENT)
00311   {
00312     cerr<<"Failed to stat pidfile '"<<_pidfile<<"': "
00313         <<STRERR_FILE_LINE<<endl;
00314     ::exit(-1);
00315   }
00316 
00317   // If process 'pidFromFile' is running then exit, else remove pidfile.
00318   if(pidFromFile>0)
00319   {
00320     if(0==::kill(pidFromFile,0)) // tests for running 'pidFromFile'.
00321     {
00322       cerr<<"Quitting because process "<<pidFromFile
00323           <<" defined in pidfile '"<<_pidfile<<"'"
00324           <<" is already running."<<endl;
00325       ::exit(-1);
00326     }
00327     else if(errno!=ESRCH)
00328     {
00329       cerr<<"Failed to test for process "<<pidFromFile
00330           <<" defined in pidfile '"<<_pidfile<<"': "
00331           <<STRERR_FILE_LINE<<endl;
00332       ::exit(-1);
00333     }
00334   }
00335 }

void Omniifr::DaemonImpl::daemonize  ) 
 

Puts the current process into the background.

Redirects the omniORB log output to syslog (or 'tracefile', if it is set).

Definition at line 158 of file daemon_unix.cc.

References _foreground, _haveSyslog, _tracefile, checkPidfileOrShutdown(), fork(), PACKAGE_NAME, redirectStreamsTo(), omniORB::setLogFunction(), Omniifr::shutdown0(), Omniifr::shutdown2(), STRERR_FILE_LINE, and writePidfile().

Referenced by Omniifr::Daemon::daemonize().

00159 {
00160   // Register the shutdown function.
00161 #ifdef HAVE_ON_EXIT
00162   if( ::on_exit(shutdown2,NULL) <0)
00163 #else
00164   if( ::atexit(shutdown0) <0)
00165 #endif
00166   {
00167     cerr<<"Failed to set exit handler."<<endl;
00168     ::exit(-1);
00169   }
00170 
00171   if(!_foreground)
00172   {
00173     this->fork();
00174   // ...now in the CHILD.
00175   }
00176 
00177   // Check & write the pidfile (if _pidfile is set).
00178   checkPidfileOrShutdown();
00179   writePidfile();
00180 
00181   // Change the file mode mask
00182   ::umask(0);
00183           
00184   // Change the current working directory
00185   if(::chdir("/")!=0)
00186   {
00187     cerr<<STRERR_FILE_LINE<<endl;
00188     ::exit(-1);
00189   }
00190 
00191   // If _tracefile is not set, then use syslog.
00192   if(_tracefile && _tracefile[0]!='\0')
00193   {
00194     redirectStreamsTo(_tracefile);
00195   }
00196   else
00197   {
00198 #ifndef HAVE_OMNIORB3
00199 #  ifdef LOG_PERROR
00200     ::openlog(PACKAGE_NAME ": ",LOG_PID|LOG_PERROR,LOG_DAEMON);
00201 #  else
00202     ::openlog(PACKAGE_NAME ": ",LOG_PID,LOG_DAEMON);
00203 #  endif
00204     _haveSyslog=true;
00205     omniORB::setLogFunction(DaemonImpl::log);
00206 #else
00207     cerr<<"You must use option -t to set the file for trace messages."
00208       "\n(This is because omniORB3 cannot redirect messages to syslog.)"<<endl;
00209     ::exit(-1);
00210 #endif
00211   }
00212 } // end daemonize()

void Omniifr::DaemonImpl::foreground bool  val  ) 
 

Set _foreground.

Definition at line 137 of file daemon_unix.cc.

References _foreground.

Referenced by Omniifr::Daemon::foreground().

00138 {
00139   _foreground=val;
00140 }

void Omniifr::DaemonImpl::fork  )  [private]
 

Performs the actual fork.

Definition at line 363 of file daemon_unix.cc.

References _haveParent, _pipe, PIPE_READ, PIPE_WRITE, STRERR_FILE_LINE, and waitForChild().

Referenced by daemonize().

00364 {
00365   if( ::pipe(_pipe) <0)
00366   {
00367     cerr<<"Failed to open pipe: "<<STRERR_FILE_LINE<<endl;
00368     ::exit(-1);
00369   }
00370 
00371   // Fork off from the parent process
00372   pid_t pid =::fork();
00373   if(pid<0)
00374   {
00375     cerr<<STRERR_FILE_LINE<<endl;
00376     ::exit(-1);
00377   }
00378   else if(pid>0)
00379   {
00380     //
00381     // Now in the PARENT
00382     //
00383 
00384     // Close the write end of the pipe.
00385     if( ::close(_pipe[PIPE_WRITE]) <0)
00386         cerr<<"Failed to close pipe: "<<STRERR_FILE_LINE<<endl;
00387 
00388     ::_exit(waitForChild()); // Exit without flushing buffers
00389   }
00390 
00391   //
00392   // ...now in the CHILD.
00393   //
00394 
00395   _haveParent=true;
00396 
00397   // Close the read end of the pipe
00398   if( ::close(_pipe[PIPE_READ]) <0)
00399       cerr<<"Failed to close pipe: "<<STRERR_FILE_LINE<<endl;
00400 
00401   // Create a new SID for the child process
00402   pid_t sid =::setsid();
00403   if(sid<0)
00404   {
00405     cerr<<STRERR_FILE_LINE<<endl;
00406     ::exit(-1);
00407   }
00408 }

void Omniifr::DaemonImpl::initialize int &  ,
char **& 
 

Does nothing on Unix.

Definition at line 152 of file daemon_unix.cc.

00153 {
00154   // Does nothing on Unix
00155 }

void Omniifr::DaemonImpl::log const char *  message  )  [static]
 

Callback, used as a parameter to omniORB::setLogFunction().

Definition at line 265 of file daemon_unix.cc.

References _haveParent, and Omniifr::daemon.

00266 {
00267   // Cut off the redundant packageNamePrefix.
00268   static const char*  packageNamePrefix    ="omniIFR: ";
00269   static const size_t packageNamePrefixLen =::strlen(packageNamePrefix);
00270   if(0==::strncmp(message,packageNamePrefix,packageNamePrefixLen))
00271       message+=packageNamePrefixLen;
00272   // Send the message.
00273   ::syslog(LOG_INFO,message);
00274 #ifndef LOG_PERROR
00275   // If we don't have LOG_PERROR, then we'll have to manually send
00276   // log messages to stderr.
00277   if(daemon._haveParent)
00278       cerr<<message<<flush;
00279 #endif
00280 }

void Omniifr::DaemonImpl::notifyParent int  status  )  [private]
 

Tells the parent to exit with the given status (Unix).

Definition at line 462 of file daemon_unix.cc.

References _pipe, PIPE_WRITE, and STRERR_FILE_LINE.

Referenced by runningOk(), and shutdown().

00463 {
00464   ssize_t r =::write(_pipe[PIPE_WRITE],&status,sizeof(status));
00465   if(r<sizeof(status))
00466   {
00467     if(r<0)
00468         cerr<<"read() failed while writing return value to pipe: "
00469             <<STRERR_FILE_LINE<<endl;
00470     else
00471         cerr<<"write() too short while writing return value from pipe: "
00472             <<STRERR_FILE_LINE<<endl;
00473   }
00474   if( ::close(_pipe[PIPE_WRITE]) !=0)
00475       cerr<<"Failed to close pipe: "<<STRERR_FILE_LINE<<endl;
00476 }

int Omniifr::DaemonImpl::openFileFor int  fd,
const char *  filename,
int  flags
[private]
 

Opens a (new?) file called 'filename' for writing, and uses it to hijack stream 'fd'.

Definition at line 431 of file daemon_unix.cc.

Referenced by redirectStreamsTo().

00432 {
00433   int newfd =::open(filename,flags,0644);
00434   if(newfd<0)
00435       return -1;
00436   if(newfd==fd)
00437       return fd;
00438   if(::dup2(newfd,fd)<0) // replace fd with a copy of newfd
00439       return -1;
00440   ::close(newfd);
00441   return fd;
00442 }

void Omniifr::DaemonImpl::pidfile const char *  val  ) 
 

Set _pidfile.

Definition at line 143 of file daemon_unix.cc.

Referenced by Omniifr::Daemon::pidfile().

00144 {
00145   string pidfileStr =val;
00146   if(pidfileStr[0]!='/')
00147       pidfileStr=string("/var/run/")+pidfileStr;
00148   DaemonImpl::_pidfile=::strdup(pidfileStr.c_str());
00149 }

void Omniifr::DaemonImpl::redirectStreamsTo const char *  filename  )  [private]
 

Redirect stdout & stderr to filename.

Also redirects stdin from /dev/null

Definition at line 411 of file daemon_unix.cc.

References openFileFor(), and STRERR_FILE_LINE.

Referenced by daemonize(), and runningOk().

00412 {
00413   if(openFileFor(STDIN_FILENO,"/dev/null",O_RDONLY)<0)
00414   {
00415     cerr<<"Failed to open /dev/null for STDIN: "<<STRERR_FILE_LINE<<endl;
00416     ::exit(-1);
00417   }
00418   if(openFileFor(STDOUT_FILENO,filename,O_WRONLY|O_CREAT|O_APPEND)<0)
00419   {
00420     cerr<<"Failed to open "<<filename<<" for STDOUT: "<<STRERR_FILE_LINE<<endl;
00421     ::exit(-1);
00422   }
00423   if(openFileFor(STDERR_FILENO,filename,O_WRONLY|O_CREAT|O_APPEND)<0)
00424   {
00425     cerr<<"Failed to open "<<filename<<" for STDERR: "<<STRERR_FILE_LINE<<endl;
00426     ::exit(-1);
00427   }
00428 }

void Omniifr::DaemonImpl::runningOk  ) 
 

Called to signal that all startup operations have completed OK.

Notifies the parent process and redirects stdout & stderr to 'tracefile' (or else /dev/null).

Definition at line 215 of file daemon_unix.cc.

References _haveParent, _haveSyslog, notifyParent(), PACKAGE_NAME, and redirectStreamsTo().

Referenced by Omniifr::Daemon::runningOk().

00216 {
00217   if(_haveParent)
00218   {
00219     _haveParent=false;
00220     notifyParent(0);
00221   }
00222 
00223   // No longer send syslog messages to stderr.
00224   if(_haveSyslog)
00225   {
00226 #ifdef LOG_PERROR
00227     ::closelog();
00228     // FIXME: Possible race here? If a log message is sent right now.
00229     ::openlog(PACKAGE_NAME ": ",LOG_PID,LOG_DAEMON);
00230 #endif
00231     redirectStreamsTo("/dev/null");
00232   }
00233 }

void Omniifr::DaemonImpl::shutdown int  status  ) 
 

Exit handler called (indirectly) by ::on_exit() - shuts down the daemon.

Deletes pidfile (if we have one), notifies the parent (if we have one).

Definition at line 236 of file daemon_unix.cc.

References _haveParent, _havePidfile, _haveSyslog, _pidfile, notifyParent(), and STRERR_FILE_LINE.

Referenced by Omniifr::shutdown0(), Omniifr::shutdown2(), and Omniifr::Daemon::~Daemon().

00237 {
00238   // Remove the pidfile.
00239   if(_havePidfile && _pidfile && 0!=::unlink(_pidfile))
00240   {
00241     cerr<<"Failed to remove pidfile '"<<_pidfile<<"': "
00242         <<STRERR_FILE_LINE<<endl;
00243     status=-1;
00244   }
00245   _havePidfile=false;
00246 
00247   // Close syslog.
00248   if(_haveSyslog)
00249   {
00250     _haveSyslog=false;
00251     ::closelog();
00252   }
00253   
00254   // Notify the parent.
00255   if(_haveParent)
00256   {
00257     _haveParent=false;
00258     notifyParent(status);
00259   }
00260 
00261   // outtahere...
00262 }

void Omniifr::DaemonImpl::tracefile const char *  val  ) 
 

Set _tracefile.

Definition at line 131 of file daemon_unix.cc.

References _tracefile.

Referenced by Omniifr::Daemon::tracefile().

00132 {
00133   _tracefile=::strdup(val);
00134 }

int Omniifr::DaemonImpl::waitForChild  )  [private]
 

Called by the parent process (Unix).

Waits for the child to return an exit status. The status is usually '0' - indicating that the daemon has started successfully.

Definition at line 445 of file daemon_unix.cc.

References _pipe, PIPE_READ, and STRERR_FILE_LINE.

Referenced by fork().

00446 {
00447   int status =-1;
00448   ssize_t bytes =::read(_pipe[PIPE_READ],&status,sizeof(status));
00449   if(bytes<sizeof(status))
00450   {
00451     status=-1;
00452     if(bytes<0)
00453        cerr<<"Parent failed to read result from pipe: "<<STRERR_FILE_LINE<<endl;
00454   }
00455   if( ::close(_pipe[PIPE_READ]) !=0)
00456       cerr<<"Failed to close pipe: "<<STRERR_FILE_LINE<<endl;
00457 
00458   return status;
00459 }

void Omniifr::DaemonImpl::writePidfile  )  [private]
 

Definition at line 338 of file daemon_unix.cc.

References _havePidfile, and _pidfile.

Referenced by daemonize().

00339 {
00340   if(_pidfile)
00341   {
00342     try
00343     {
00344 #ifdef FSTREAM_OPEN_PROT
00345       ofstream outfile(_pidfile,ios::out|ios::trunc,0644);
00346 #else
00347       ofstream outfile(_pidfile,ios::out|ios::trunc);
00348 #endif
00349       outfile<<::getpid()<<endl;
00350       outfile.close();
00351       // Tell shutdown() that the pidfile needs to be cleared away.
00352       _havePidfile=true;
00353     }
00354     catch(...)
00355     {
00356       cerr<<"Failed to write pidfile '"<<_pidfile<<"'."<<endl;
00357       ::exit(-1);
00358     }
00359   }
00360 }


Member Data Documentation

bool Omniifr::DaemonImpl::_foreground
 

TRUE for debug mode (run in foreground).

Definition at line 43 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), daemonize(), and foreground().

bool Omniifr::DaemonImpl::_haveParent
 

Is there a parent for us to clean up?

Definition at line 47 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), fork(), log(), runningOk(), and shutdown().

bool Omniifr::DaemonImpl::_havePidfile
 

Is there a pidfile for us to clean up?

Definition at line 46 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), shutdown(), and writePidfile().

bool Omniifr::DaemonImpl::_haveSyslog
 

Should we close syslog before quitting?

Definition at line 48 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), daemonize(), runningOk(), and shutdown().

DaemonImpl Omniifr::DaemonImpl::_inst [static]
 

Definition at line 40 of file daemon_unix.h.

char* Omniifr::DaemonImpl::_pidfile
 

The pidfile name (if any).

Definition at line 44 of file daemon_unix.h.

Referenced by checkPidfileOrShutdown(), Omniifr::Daemon::Daemon(), shutdown(), writePidfile(), and ~DaemonImpl().

int Omniifr::DaemonImpl::_pipe[2]
 

Unnamed pipe for child->parent comms.

Definition at line 45 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), fork(), notifyParent(), and waitForChild().

char* Omniifr::DaemonImpl::_tracefile
 

The tracefile name (if any).

Definition at line 42 of file daemon_unix.h.

Referenced by Omniifr::Daemon::Daemon(), daemonize(), tracefile(), and ~DaemonImpl().


The documentation for this class was generated from the following files:
Generated on Fri Mar 4 13:03:58 2005 for OmniIFR by  doxygen 1.4.1