Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * daemonize.cpp - Fawkes daemonization functions 00004 * 00005 * Created: Wed May 04 23:33:33 2011 00006 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <baseapp/daemonize.h> 00025 00026 #include <utils/system/argparser.h> 00027 00028 #include <unistd.h> 00029 #include <sys/types.h> 00030 #include <cstdio> 00031 #ifdef HAVE_LIBDAEMON 00032 # include <cerrno> 00033 # include <cstring> 00034 # include <csignal> 00035 # include <libdaemon/dfork.h> 00036 # include <libdaemon/dlog.h> 00037 # include <libdaemon/dpid.h> 00038 # include <sys/stat.h> 00039 # include <sys/wait.h> 00040 #endif 00041 00042 namespace fawkes { 00043 namespace daemon { 00044 #if 0 /* just to make Emacs auto-indent happy */ 00045 } 00046 } 00047 #endif 00048 00049 #ifdef HAVE_LIBDAEMON 00050 /** Global variable containing the path to the PID file. 00051 * unfortunately needed for libdaemon */ 00052 const char *fawkes_pid_file; 00053 00054 /** Function that returns the PID file name. 00055 * @return PID file name 00056 */ 00057 const char * 00058 fawkes_daemon_pid_file_proc() 00059 { 00060 return fawkes_pid_file; 00061 } 00062 #endif // HAVE_LIBDAEMON 00063 00064 00065 pid_t 00066 daemonize() 00067 { 00068 #ifdef HAVE_LIBDAEMON 00069 pid_t pid; 00070 mode_t old_umask = umask(0); 00071 00072 // Prepare for return value passing 00073 daemon_retval_init(); 00074 00075 // Do the fork 00076 if ((pid = daemon_fork()) < 0) { 00077 return -1; 00078 00079 } else if (pid) { // the parent 00080 int ret; 00081 00082 // Wait for 20 seconds for the return value passed from the daemon process 00083 if ((ret = daemon_retval_wait(20)) < 0) { 00084 daemon_log(LOG_ERR, "Could not recieve return value from daemon process."); 00085 return -1; 00086 } 00087 00088 if ( ret != 0 ) { 00089 daemon_log(LOG_ERR, "*** Daemon startup failed, see syslog for details. ***"); 00090 switch (ret) { 00091 case 1: 00092 daemon_log(LOG_ERR, "Daemon failed to close file descriptors"); 00093 break; 00094 case 2: 00095 daemon_log(LOG_ERR, "Daemon failed to create PID file"); 00096 break; 00097 } 00098 return -1; 00099 } else { 00100 return pid; 00101 } 00102 00103 } else { // the daemon 00104 #ifdef DAEMON_CLOSE_ALL_AVAILABLE 00105 if (daemon_close_all(-1) < 0) { 00106 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); 00107 // Send the error condition to the parent process 00108 daemon_retval_send(1); 00109 return -1; 00110 } 00111 #endif 00112 00113 // Create the PID file 00114 if (daemon_pid_file_create() < 0) { 00115 printf("Could not create PID file (%s).", strerror(errno)); 00116 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); 00117 00118 // Send the error condition to the parent process 00119 daemon_retval_send(2); 00120 return -1; 00121 } 00122 00123 // Send OK to parent process 00124 daemon_retval_send(0); 00125 00126 daemon_log(LOG_INFO, "Sucessfully started"); 00127 00128 umask(old_umask); 00129 return 0; 00130 } 00131 #else 00132 throw Exception("Daemonizing support is not available.\n" 00133 "(libdaemon[-devel] was not available at compile time)\n"); 00134 #endif 00135 } 00136 00137 00138 void 00139 init(const char *pidfile, const char *progname) 00140 { 00141 #ifdef HAVE_LIBDAEMON 00142 // Set identification string for the daemon for both syslog and PID file 00143 daemon_pid_file_ident = daemon_log_ident = 00144 daemon_ident_from_argv0((char *)progname); 00145 if ( pidfile != NULL ) { 00146 fawkes_pid_file = pidfile; 00147 daemon_pid_file_proc = fawkes_daemon_pid_file_proc; 00148 } 00149 #else 00150 throw Exception("Daemonizing support is not available.\n" 00151 "(libdaemon[-devel] was not available at compile time)\n"); 00152 #endif 00153 } 00154 00155 bool 00156 start() 00157 { 00158 #ifdef HAVE_LIBDAEMON 00159 pid_t pid; 00160 00161 // Check that the daemon is not run twice a the same time 00162 if ((pid = daemon_pid_file_is_running()) >= 0) { 00163 daemon_log(LOG_ERR, "Daemon already running on (PID %u)", pid); 00164 throw Exception("Daemon already running on (PID %u)", pid); 00165 } 00166 00167 pid = daemonize(); 00168 if ( pid < 0 ) { 00169 cleanup(); 00170 throw Exception("Failed to daemonize"); 00171 } else if (pid) { 00172 // parent 00173 return true; 00174 } else { 00175 // child 00176 return false; 00177 } 00178 #else 00179 throw Exception("Daemonizing support is not available.\n" 00180 "(libdaemon[-devel] was not available at compile time)\n"); 00181 #endif 00182 } 00183 00184 bool 00185 running() 00186 { 00187 #ifdef HAVE_LIBDAEMON 00188 return (daemon_pid_file_is_running() >= 0); 00189 #else 00190 throw Exception("Daemonizing support is not available.\n" 00191 "(libdaemon[-devel] was not available at compile time)\n"); 00192 #endif 00193 } 00194 00195 00196 void 00197 kill() 00198 { 00199 #ifdef HAVE_LIBDAEMON 00200 pid_t pid; 00201 int ret; 00202 00203 // Check that the daemon is not run twice a the same time 00204 if ((pid = daemon_pid_file_is_running()) < 0) { 00205 daemon_log(LOG_WARNING, "Fawkes daemon not running."); 00206 } 00207 00208 // Kill daemon with SIGINT 00209 if ((ret = daemon_pid_file_kill_wait(SIGINT, 5)) < 0) { 00210 daemon_log(LOG_WARNING, "Failed to kill daemon"); 00211 } 00212 #else 00213 throw Exception("Daemonizing support is not available.\n" 00214 "(libdaemon[-devel] was not available at compile time)\n"); 00215 #endif 00216 } 00217 00218 00219 void 00220 cleanup() 00221 { 00222 #ifdef HAVE_LIBDAEMON 00223 daemon_retval_send(-1); 00224 daemon_retval_done(); 00225 daemon_pid_file_remove(); 00226 #else 00227 throw Exception("Daemonizing support is not available.\n" 00228 "(libdaemon[-devel] was not available at compile time)\n"); 00229 #endif 00230 } 00231 00232 00233 00234 } // end namespace fawkes::daemon 00235 } // end namespace fawkes