#include <daemon_unix.h>
Collaboration diagram for Omniifr::DaemonImpl:
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). |
Features: pidfile support, forking, redirect omniORB trace to syslog (or tracefile).
Definition at line 37 of file daemon_unix.h.
|
Definition at line 119 of file daemon_unix.cc. 00119 {}
|
|
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 }
|
|
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 }
|
|
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()
|
|
Set _foreground.
Definition at line 137 of file daemon_unix.cc. References _foreground. Referenced by Omniifr::Daemon::foreground(). 00138 { 00139 _foreground=val; 00140 }
|
|
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 }
|
|
Does nothing on Unix.
Definition at line 152 of file daemon_unix.cc. 00153 {
00154 // Does nothing on Unix
00155 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
Set _tracefile.
Definition at line 131 of file daemon_unix.cc. References _tracefile. Referenced by Omniifr::Daemon::tracefile(). 00132 { 00133 _tracefile=::strdup(val); 00134 }
|
|
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 }
|
|
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 }
|
|
TRUE for debug mode (run in foreground).
Definition at line 43 of file daemon_unix.h. Referenced by Omniifr::Daemon::Daemon(), daemonize(), and foreground(). |
|
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(). |
|
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(). |
|
Should we close syslog before quitting?
Definition at line 48 of file daemon_unix.h. Referenced by Omniifr::Daemon::Daemon(), daemonize(), runningOk(), and shutdown(). |
|
Definition at line 40 of file daemon_unix.h. |
|
The pidfile name (if any).
Definition at line 44 of file daemon_unix.h. Referenced by checkPidfileOrShutdown(), Omniifr::Daemon::Daemon(), shutdown(), writePidfile(), and ~DaemonImpl(). |
|
Unnamed pipe for child->parent comms.
Definition at line 45 of file daemon_unix.h. Referenced by Omniifr::Daemon::Daemon(), fork(), notifyParent(), and waitForChild(). |
|
The tracefile name (if any).
Definition at line 42 of file daemon_unix.h. Referenced by Omniifr::Daemon::Daemon(), daemonize(), tracefile(), and ~DaemonImpl(). |