19 #ifdef HAVE_SYS_INOTIFY_H
20 #include <sys/inotify.h>
28 psignals psignals::thread;
30 psignals::psignals() :
33 shutdown = started =
false;
42 void psignals::cancel(
void)
49 pthread_kill(tid, SIGALRM);
54 void psignals::run(
void)
57 unsigned period = 900;
60 shell::log(
DEBUG1,
"starting signal handler");
65 int result = sigwait(&sigs, &signo);
68 shell::log(shell::ERR,
"signal handler error %d", errno);
73 signo = sigwait(&sigs);
76 shell::log(shell::ERR,
"signal handler error %d", errno);
85 shell::log(
DEBUG1,
"received signal %d", signo);
89 shell::log(shell::INFO,
"system housekeeping");
96 control::send(
"down");
99 control::send(
"snapshot");
102 control::send(
"reload");
108 shell::log(
DEBUG1,
"stopping signal handler");
111 void psignals::service(
const char *
name)
115 void psignals::setup(
void)
117 sigemptyset(&thread.sigs);
118 sigaddset(&thread.sigs, SIGALRM);
119 sigaddset(&thread.sigs, SIGHUP);
120 sigaddset(&thread.sigs, SIGINT);
121 sigaddset(&thread.sigs, SIGTERM);
122 sigaddset(&thread.sigs, SIGUSR1);
123 pthread_sigmask(SIG_BLOCK, &thread.sigs, NULL);
125 signal(SIGPIPE, SIG_IGN);
128 void psignals::start(
void)
133 void psignals::stop(
void)
140 static SERVICE_STATUS_HANDLE hStatus = 0;
141 static SERVICE_STATUS status;
143 static void WINAPI handler(DWORD sigint)
151 case SERVICE_CONTROL_SHUTDOWN:
152 case SERVICE_CONTROL_STOP:
153 status.dwCurrentState = SERVICE_STOP_PENDING;
154 status.dwWin32ExitCode = 0;
155 status.dwCheckPoint = 0;
156 status.dwWaitHint = 6000;
157 SetServiceStatus(hStatus, &status);
165 void psignals::service(
const char *
name)
167 memset(&status, 0,
sizeof(SERVICE_STATUS));
168 status.dwServiceType = SERVICE_WIN32;
169 status.dwCurrentState = SERVICE_START_PENDING;
170 status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
171 hStatus = ::RegisterServiceCtrlHandler(name, &handler);
174 void psignals::setup(
void)
178 void psignals::start(
void)
183 status.dwCurrentState = SERVICE_RUNNING;
184 ::SetServiceStatus(hStatus, &status);
187 void psignals::stop(
void)
192 status.dwCurrentState = SERVICE_STOPPED;
193 ::SetServiceStatus(hStatus, &status);
198 void psignals::service(
const char *name)
202 void psignals::setup(
void)
206 void psignals::start(
void)
210 void psignals::stop(
void)
216 #ifdef HAVE_SYS_INOTIFY_H
218 static const char *dirpath = NULL;
219 static const char *cachepath = NULL;
220 static fd_t watcher = -1;
221 static uint32_t dirnode;
222 static uint32_t cachenode;
243 if(fsys::is_dir(dirpath))
246 shell::log(shell::ERR,
"notify failed; %s missing", dirpath);
249 void notify::run(
void)
251 static bool logged =
false;
252 timeout_t timeout = -1;
253 unsigned updates = 0;
256 shell::log(
DEBUG1,
"notify watching %s", dirpath);
258 watcher = inotify_init();
259 dirnode = inotify_add_watch(watcher, dirpath, IN_CLOSE_WRITE|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE|IN_DONT_FOLLOW);
261 cachenode = inotify_add_watch(watcher, cachepath, IN_CLOSE_WRITE|IN_MOVED_TO|IN_MOVED_FROM|IN_DELETE|IN_DONT_FOLLOW);
262 shell::log(
DEBUG1,
"notify watching cache %s", cachepath);
265 while(watcher != -1) {
273 pfd.events = POLLIN | POLLNVAL | POLLERR;
275 int result = poll(&pfd, 1, timeout);
279 shell::log(shell::ERR,
"notify error %d", errno);
295 if(pfd.revents & (POLLNVAL|POLLERR))
298 if(pfd.revents & POLLIN) {
302 size_t len = ::read(watcher, &buffer,
sizeof(buffer));
303 if(len <
sizeof(
struct inotify_event)) {
304 shell::log(shell::ERR,
"notify failed to read inotify");
308 while(offset < len) {
309 struct inotify_event *
event = (
struct inotify_event *)&buffer[offset];
314 const char *ext = strrchr(event->name,
'.');
315 if(ext && eq_case(ext,
".xml")) {
316 shell::log(
DEBUG2,
"%s updated", event->name);
319 offset +=
sizeof(
struct inotify_event) + event->len;
324 shell::log(
DEBUG1,
"notify terminating");
static bool send(const char *format,...) __PRINTF(1
Send a printf-style message to the control fifo via the file system.
static const char * env(const char *id)
Return the value of a server environment variable.