2 * UCW Library -- Daemon Control
4 * (c) 2012 Martin Mares <mj@ucw.cz>
5 * (c) 2014 Pavel Charvat <pchar@ucw.cz>
7 * This software may be freely distributed and used according to the terms
8 * of the GNU Lesser General Public License.
12 #include <ucw/daemon.h>
13 #include <ucw/process.h>
14 #include <ucw/strtonum.h>
27 static enum daemon_control_status
28 daemon_control_err(struct daemon_control_params *dc, char *msg, ...)
32 vsnprintf(dc->error_msg, DAEMON_ERR_LEN, msg, args);
34 return DAEMON_STATUS_ERROR;
37 static enum daemon_control_status
38 daemon_read_pid(struct daemon_control_params *dc, int will_wait, int *pidp)
40 // We expect successfully locked guard file, so no foreign process
41 // can be inside daemon_control() and therefore also in daemon_init()
42 // or daemon_run(). Only these results are then possible:
44 // -- DAEMON_STATUS_ERROR -- some local failure
45 // -- DAEMON_STATUS_NOT_RUNNING -- no daemon is running
46 // -- DAEMON_STATUS_STALE -- crashed daemon
47 // -- DAEMON_STATUS_OK, pid > 0 -- running daemon with known PID
48 // -- DAEMON_STATUS_OK, pid == 0 -- just exiting daemon, after ftruncate()
50 enum daemon_control_status st = DAEMON_STATUS_NOT_RUNNING;
53 int pid_fd = open(dc->pid_file, O_RDONLY);
58 return daemon_control_err(dc, "Cannot open PID file `%s': %m", dc->pid_file);
61 while (flock(pid_fd, LOCK_SH | (will_wait ? 0 : LOCK_NB)) < 0)
63 if (errno == EWOULDBLOCK)
65 st = DAEMON_STATUS_OK;
68 else if (errno != EINTR)
70 daemon_control_err(dc, "Cannot lock PID file `%s': %m", dc->pid_file);
76 int n = read(pid_fd, buf, sizeof(buf));
79 daemon_control_err(dc, "Error reading `%s': %m", dc->pid_file);
82 if (n == (int) sizeof(buf))
84 daemon_control_err(dc, "PID file `%s' is too long", dc->pid_file);
95 if (st != DAEMON_STATUS_OK)
98 return DAEMON_STATUS_STALE;
103 if (str_to_int(&pid, buf, &next, 10) || strcmp(next, "\n"))
105 daemon_control_err(dc, "PID file `%s' does not contain a valid PID", dc->pid_file);
111 return DAEMON_STATUS_OK;
115 return DAEMON_STATUS_ERROR;
118 enum daemon_control_status
119 daemon_control(struct daemon_control_params *dc)
121 int guard_fd = open(dc->guard_file, O_RDWR | O_CREAT, 0666);
123 return daemon_control_err(dc, "Cannot open guard file `%s': %m", dc->guard_file);
124 if (flock(guard_fd, LOCK_EX) < 0)
125 return daemon_control_err(dc, "Cannot lock guard file `%s': %m", dc->guard_file);
129 enum daemon_control_status st = daemon_read_pid(dc, 0, &pid);
130 if (st == DAEMON_STATUS_ERROR)
135 case DAEMON_CONTROL_CHECK:
137 case DAEMON_CONTROL_START:
138 if (st == DAEMON_STATUS_OK)
139 st = DAEMON_STATUS_ALREADY_DONE;
145 st = daemon_control_err(dc, "Cannot fork: %m");
151 execvp(dc->argv[0], dc->argv);
152 fprintf(stderr, "Cannot execute `%s': %m\n", dc->argv[0]);
153 exit(DAEMON_STATUS_ERROR);
156 int ec = waitpid(pp, &stat, 0);
159 st = daemon_control_err(dc, "Cannot wait: %m");
162 if (WIFEXITED(stat) && WEXITSTATUS(stat) == DAEMON_STATUS_ERROR)
164 st = daemon_control_err(dc, "Cannot execute the daemon");
167 char ecmsg[EXIT_STATUS_MSG_SIZE];
168 if (format_exit_status(ecmsg, stat))
170 st = daemon_control_err(dc, "Daemon %s %s", dc->argv[0], ecmsg);
173 enum daemon_control_status st2 = daemon_read_pid(dc, 0, &pid);
174 if (st2 != DAEMON_STATUS_OK && st2 != DAEMON_STATUS_NOT_RUNNING)
175 st = daemon_control_err(dc, "Daemon %s failed to write the PID file `%s'", dc->argv[0], dc->pid_file);
176 else if (st != DAEMON_STATUS_STALE)
177 st = DAEMON_STATUS_OK;
180 case DAEMON_CONTROL_STOP:
181 if (st != DAEMON_STATUS_OK)
183 if (st == DAEMON_STATUS_NOT_RUNNING)
184 st = DAEMON_STATUS_ALREADY_DONE;
189 sig = dc->signal ? : SIGTERM;
190 if (kill(pid, sig) < 0 && errno != ESRCH)
192 st = daemon_control_err(dc, "Cannot send signal %d: %m", sig);
198 // Just exiting daemon => we can safely wait without sending any signal
200 st = daemon_read_pid(dc, 1, &pid);
201 if (st != DAEMON_STATUS_ERROR)
202 st = DAEMON_STATUS_OK;
204 case DAEMON_CONTROL_SIGNAL:
206 return DAEMON_STATUS_NOT_RUNNING;
207 sig = dc->signal ? : SIGHUP;
208 if (kill(pid, sig) >= 0)
209 st = DAEMON_STATUS_OK;
210 else if (errno == ESRCH)
211 st = DAEMON_STATUS_NOT_RUNNING;
213 st = daemon_control_err(dc, "Cannot send signal %d: %m", sig);