root/src/noit_main.c

Revision 86e0c6af3530e751a8676f651a2477e300e494f1, 7.9 kB (checked in by Philip Maddox <pmaddox@circonus.com>, 2 years ago)

Removed retries and span from noit_watchdog_start_child and added function to set them in watchdog

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2011, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 #include "noit_defines.h"
33
34 #include <assert.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <sys/mman.h>
41 #include <signal.h>
42 #ifdef HAVE_SYS_WAIT_H
43 #include <sys/wait.h>
44 #endif
45
46 #include "utils/noit_log.h"
47 #include "noit_conf.h"
48 #include "utils/noit_security.h"
49 #include "utils/noit_watchdog.h"
50 #include "utils/noit_lockfile.h"
51 #include "eventer/eventer.h"
52
53 #define MAX_CLI_LOGS 128
54 static char *enable_logs[MAX_CLI_LOGS];
55 static int enable_logs_cnt = 0;
56 static char *disable_logs[MAX_CLI_LOGS];
57 static int disable_logs_cnt = 0;
58
59 void
60 noit_main_enable_log(const char *name) {
61   if(enable_logs_cnt >= MAX_CLI_LOGS) return;
62   enable_logs[enable_logs_cnt++] = strdup(name);
63 }
64 void
65 noit_main_disable_log(const char *name) {
66   if(disable_logs_cnt >= MAX_CLI_LOGS) return;
67   disable_logs[disable_logs_cnt++] = strdup(name);
68 }
69 static int
70 configure_eventer(const char *appname) {
71   int rv = 0;
72   noit_hash_table *table;
73   char appscratch[1024];
74
75   snprintf(appscratch, sizeof(appscratch), "/%s/eventer/config", appname);
76   table = noit_conf_get_hash(NULL, appscratch);
77   if(table) {
78     noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
79     const char *key, *value;
80     int klen;
81     while(noit_hash_next_str(table, &iter, &key, &klen, &value)) {
82       int subrv;
83       if((subrv = eventer_propset(key, value)) != 0)
84         rv = subrv;
85     }
86     noit_hash_destroy(table, free, free);
87     free(table);
88   }
89   return rv;
90 }
91
92 void cli_log_switches() {
93   int i;
94   noit_log_stream_t ls;
95   for(i=0; i<enable_logs_cnt; i++) {
96     ls = noit_log_stream_find(enable_logs[i]);
97     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
98     if(ls && !ls->enabled) {
99       noitL(noit_error, "Enabling %s\n", enable_logs[i]);
100       ls->enabled = 1;
101     }
102   }
103   for(i=0; i<disable_logs_cnt; i++) {
104     ls = noit_log_stream_find(disable_logs[i]);
105     if(!ls) noitL(noit_error, "No such log: '%s'\n", enable_logs[i]);
106     if(ls && ls->enabled) {
107       noitL(noit_error, "Disabling %s\n", disable_logs[i]);
108       ls->enabled = 0;
109     }
110   }
111 }
112
113 int
114 noit_main(const char *appname,
115           const char *config_filename, int debug, int foreground,
116           const char *_glider,
117           const char *drop_to_user, const char *drop_to_group,
118           int (*passed_child_main)(void)) {
119   int fd, lockfd, watchdog_timeout = 0;
120   char conf_str[1024];
121   char lockfile[PATH_MAX];
122   char user[32], group[32];
123   char *trace_dir = NULL;
124   char appscratch[1024];
125   char *glider = (char *)_glider;
126   char *watchdog_timeout_str;
127   int retry_val;
128   int span_val;
129   int ret;
130  
131    
132   /* First initialize logging, so we can log errors */
133   noit_log_init();
134   noit_log_stream_add_stream(noit_debug, noit_stderr);
135   noit_log_stream_add_stream(noit_error, noit_stderr);
136
137   /* Next load the configs */
138   noit_conf_init(appname);
139   if(noit_conf_load(config_filename) == -1) {
140     fprintf(stderr, "Cannot load config: '%s'\n", config_filename);
141     exit(-1);
142   }
143
144   /* Reinitialize the logging system now that we have a config */
145   snprintf(user, sizeof(user), "%d", getuid());
146   snprintf(group, sizeof(group), "%d", getgid());
147   if(noit_security_usergroup(drop_to_user, drop_to_group, noit_true)) {
148     noitL(noit_stderr, "Failed to drop privileges, exiting.\n");
149     exit(-1);
150   }
151   noit_conf_log_init(appname);
152   cli_log_switches();
153   if(noit_security_usergroup(user, group, noit_true)) {
154     noitL(noit_stderr, "Failed to regain privileges, exiting.\n");
155     exit(-1);
156   }
157   if(debug)
158     noit_debug->enabled = 1;
159
160   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@glider", appname);
161   if(!glider) noit_conf_get_string(NULL, appscratch, &glider);
162   noit_watchdog_glider(glider);
163   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@tracedir", appname);
164   noit_conf_get_string(NULL, appscratch, &trace_dir);
165   if(trace_dir) noit_watchdog_glider_trace_dir(trace_dir);
166
167   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@retries", appname);
168   ret = noit_conf_get_int(NULL, appscratch, &retry_val);
169   if((ret == 0) || (retry_val == 0)){
170     retry_val = 5;
171   }
172   snprintf(appscratch, sizeof(appscratch), "/%s/watchdog/@span", appname);
173   ret = noit_conf_get_int(NULL, appscratch, &span_val);
174   if((ret == 0) || (span_val == 0)){
175     span_val = 60;
176   }
177
178   noit_watchdog_ratelimit(retry_val, span_val);
179
180   /* Lastly, run through all other system inits */
181   snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname);
182   if(!noit_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) {
183     noitL(noit_stderr, "Cannot find '%s' in configuration\n", appscratch);
184     exit(-1);
185   }
186   if(eventer_choose(conf_str) == -1) {
187     noitL(noit_stderr, "Cannot choose eventer %s\n", conf_str);
188     exit(-1);
189   }
190   if(configure_eventer(appname) != 0) {
191     noitL(noit_stderr, "Cannot configure eventer\n");
192     exit(-1);
193   }
194
195   noit_watchdog_prefork_init();
196
197   if(chdir("/") != 0) {
198     noitL(noit_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno));
199     exit(-1);
200   }
201
202   /* Acquire the lock so that we can throw an error if it doesn't work.
203    * If we've started -D, we'll have the lock.
204    * If not we will daemon and must reacquire the lock.
205    */
206   lockfd = -1;
207   lockfile[0] = '\0';
208   snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname);
209   if(noit_conf_get_stringbuf(NULL, appscratch,
210                              lockfile, sizeof(lockfile))) {
211     if((lockfd = noit_lockfile_acquire(lockfile)) < 0) {
212       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
213       exit(-1);
214     }
215   }
216
217   if(foreground) return passed_child_main();
218
219   watchdog_timeout_str = getenv("WATCHDOG_TIMEOUT");
220   if(watchdog_timeout_str) {
221     watchdog_timeout = atoi(watchdog_timeout_str);
222     noitL(noit_error, "Setting watchdog timeout to %d\n",
223           watchdog_timeout);
224   }
225
226   /* This isn't inherited across forks... */
227   if(lockfd >= 0) noit_lockfile_release(lockfd);
228
229   fd = open("/dev/null", O_RDWR);
230   dup2(fd, STDIN_FILENO);
231   dup2(fd, STDOUT_FILENO);
232   dup2(fd, STDERR_FILENO);
233   if(fork()) exit(0);
234   setsid();
235   if(fork()) exit(0);
236
237   /* Reacquire the lock */
238   if(*lockfile) {
239     if(noit_lockfile_acquire(lockfile) < 0) {
240       noitL(noit_stderr, "Failed to acquire lock: %s\n", lockfile);
241       exit(-1);
242     }
243   }
244
245   signal(SIGHUP, SIG_IGN);
246   return noit_watchdog_start_child("noitd", passed_child_main, watchdog_timeout);
247 }
Note: See TracBrowser for help on using the browser.