1 1.1 haad /* $NetBSD: dmeventd.c,v 1.1.1.1 2008/12/22 00:18:53 haad Exp $ */ 2 1.1 haad 3 1.1 haad /* 4 1.1 haad * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. 5 1.1 haad * 6 1.1 haad * This file is part of the device-mapper userspace tools. 7 1.1 haad * 8 1.1 haad * This copyrighted material is made available to anyone wishing to use, 9 1.1 haad * modify, copy, or redistribute it subject to the terms and conditions 10 1.1 haad * of the GNU Lesser General Public License v.2.1. 11 1.1 haad * 12 1.1 haad * You should have received a copy of the GNU Lesser General Public License 13 1.1 haad * along with this program; if not, write to the Free Software Foundation, 14 1.1 haad * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15 1.1 haad */ 16 1.1 haad 17 1.1 haad /* 18 1.1 haad * dmeventd - dm event daemon to monitor active mapped devices 19 1.1 haad */ 20 1.1 haad 21 1.1 haad #define _GNU_SOURCE 22 1.1 haad #define _FILE_OFFSET_BITS 64 23 1.1 haad 24 1.1 haad #include "configure.h" 25 1.1 haad #include "libdevmapper.h" 26 1.1 haad #include "libdevmapper-event.h" 27 1.1 haad #include "dmeventd.h" 28 1.1 haad //#include "libmultilog.h" 29 1.1 haad #include "dm-logging.h" 30 1.1 haad 31 1.1 haad #include <dlfcn.h> 32 1.1 haad #include <errno.h> 33 1.1 haad #include <pthread.h> 34 1.1 haad #include <sys/file.h> 35 1.1 haad #include <sys/stat.h> 36 1.1 haad #include <sys/wait.h> 37 1.1 haad #include <sys/time.h> 38 1.1 haad #include <sys/resource.h> 39 1.1 haad #include <unistd.h> 40 1.1 haad #include <signal.h> 41 1.1 haad #include <arpa/inet.h> /* for htonl, ntohl */ 42 1.1 haad 43 1.1 haad #ifdef linux 44 1.1 haad # include <malloc.h> 45 1.1 haad 46 1.1 haad # define OOM_ADJ_FILE "/proc/self/oom_adj" 47 1.1 haad 48 1.1 haad /* From linux/oom.h */ 49 1.1 haad # define OOM_DISABLE (-17) 50 1.1 haad # define OOM_ADJUST_MIN (-16) 51 1.1 haad 52 1.1 haad #endif 53 1.1 haad 54 1.1 haad /* FIXME We use syslog for now, because multilog is not yet implemented */ 55 1.1 haad #include <syslog.h> 56 1.1 haad 57 1.1 haad static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */ 58 1.1 haad static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are empty initially */ 59 1.1 haad static int _debug = 0; 60 1.1 haad 61 1.1 haad /* List (un)link macros. */ 62 1.1 haad #define LINK(x, head) dm_list_add(head, &(x)->list) 63 1.1 haad #define LINK_DSO(dso) LINK(dso, &_dso_registry) 64 1.1 haad #define LINK_THREAD(thread) LINK(thread, &_thread_registry) 65 1.1 haad 66 1.1 haad #define UNLINK(x) dm_list_del(&(x)->list) 67 1.1 haad #define UNLINK_DSO(x) UNLINK(x) 68 1.1 haad #define UNLINK_THREAD(x) UNLINK(x) 69 1.1 haad 70 1.1 haad #define DAEMON_NAME "dmeventd" 71 1.1 haad 72 1.1 haad /* 73 1.1 haad Global mutex for thread list access. Has to be held when: 74 1.1 haad - iterating thread list 75 1.1 haad - adding or removing elements from thread list 76 1.1 haad - changing or reading thread_status's fields: 77 1.1 haad processing, status, events 78 1.1 haad Use _lock_mutex() and _unlock_mutex() to hold/release it 79 1.1 haad */ 80 1.1 haad static pthread_mutex_t _global_mutex; 81 1.1 haad 82 1.1 haad /* 83 1.1 haad There are three states a thread can attain (see struct 84 1.1 haad thread_status, field int status): 85 1.1 haad 86 1.1 haad - DM_THREAD_RUNNING: thread has started up and is either working or 87 1.1 haad waiting for events... transitions to either SHUTDOWN or DONE 88 1.1 haad - DM_THREAD_SHUTDOWN: thread is still doing something, but it is 89 1.1 haad supposed to terminate (and transition to DONE) as soon as it 90 1.1 haad finishes whatever it was doing at the point of flipping state to 91 1.1 haad SHUTDOWN... the thread is still on the thread list 92 1.1 haad - DM_THREAD_DONE: thread has terminated and has been moved over to 93 1.1 haad unused thread list, cleanup pending 94 1.1 haad */ 95 1.1 haad #define DM_THREAD_RUNNING 0 96 1.1 haad #define DM_THREAD_SHUTDOWN 1 97 1.1 haad #define DM_THREAD_DONE 2 98 1.1 haad 99 1.1 haad #define THREAD_STACK_SIZE (300*1024) 100 1.1 haad 101 1.1 haad #define DEBUGLOG(fmt, args...) _debuglog(fmt, ## args) 102 1.1 haad 103 1.1 haad /* Data kept about a DSO. */ 104 1.1 haad struct dso_data { 105 1.1 haad struct dm_list list; 106 1.1 haad 107 1.1 haad char *dso_name; /* DSO name (eg, "evms", "dmraid", "lvm2"). */ 108 1.1 haad 109 1.1 haad void *dso_handle; /* Opaque handle as returned from dlopen(). */ 110 1.1 haad unsigned int ref_count; /* Library reference count. */ 111 1.1 haad 112 1.1 haad /* 113 1.1 haad * Event processing. 114 1.1 haad * 115 1.1 haad * The DSO can do whatever appropriate steps if an event 116 1.1 haad * happens such as changing the mapping in case a mirror 117 1.1 haad * fails, update the application metadata etc. 118 1.1 haad * 119 1.1 haad * This function gets a dm_task that is a result of 120 1.1 haad * DM_DEVICE_WAITEVENT ioctl (results equivalent to 121 1.1 haad * DM_DEVICE_STATUS). It should not destroy it. 122 1.1 haad * The caller must dispose of the task. 123 1.1 haad */ 124 1.1 haad void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user); 125 1.1 haad 126 1.1 haad /* 127 1.1 haad * Device registration. 128 1.1 haad * 129 1.1 haad * When an application registers a device for an event, the DSO 130 1.1 haad * can carry out appropriate steps so that a later call to 131 1.1 haad * the process_event() function is sane (eg, read metadata 132 1.1 haad * and activate a mapping). 133 1.1 haad */ 134 1.1 haad int (*register_device)(const char *device, const char *uuid, int major, 135 1.1 haad int minor, void **user); 136 1.1 haad 137 1.1 haad /* 138 1.1 haad * Device unregistration. 139 1.1 haad * 140 1.1 haad * In case all devices of a mapping (eg, RAID10) are unregistered 141 1.1 haad * for events, the DSO can recognize this and carry out appropriate 142 1.1 haad * steps (eg, deactivate mapping, metadata update). 143 1.1 haad */ 144 1.1 haad int (*unregister_device)(const char *device, const char *uuid, 145 1.1 haad int major, int minor, void **user); 146 1.1 haad }; 147 1.1 haad static DM_LIST_INIT(_dso_registry); 148 1.1 haad 149 1.1 haad /* Structure to keep parsed register variables from client message. */ 150 1.1 haad struct message_data { 151 1.1 haad char *id; 152 1.1 haad char *dso_name; /* Name of DSO. */ 153 1.1 haad char *device_uuid; /* Mapped device path. */ 154 1.1 haad union { 155 1.1 haad char *str; /* Events string as fetched from message. */ 156 1.1 haad enum dm_event_mask field; /* Events bitfield. */ 157 1.1 haad } events; 158 1.1 haad union { 159 1.1 haad char *str; 160 1.1 haad uint32_t secs; 161 1.1 haad } timeout; 162 1.1 haad struct dm_event_daemon_message *msg; /* Pointer to message buffer. */ 163 1.1 haad }; 164 1.1 haad 165 1.1 haad /* 166 1.1 haad * Housekeeping of thread+device states. 167 1.1 haad * 168 1.1 haad * One thread per mapped device which can block on it until an event 169 1.1 haad * occurs and the event processing function of the DSO gets called. 170 1.1 haad */ 171 1.1 haad struct thread_status { 172 1.1 haad struct dm_list list; 173 1.1 haad 174 1.1 haad pthread_t thread; 175 1.1 haad 176 1.1 haad struct dso_data *dso_data; /* DSO this thread accesses. */ 177 1.1 haad 178 1.1 haad struct { 179 1.1 haad char *uuid; 180 1.1 haad char *name; 181 1.1 haad int major, minor; 182 1.1 haad } device; 183 1.1 haad uint32_t event_nr; /* event number */ 184 1.1 haad int processing; /* Set when event is being processed */ 185 1.1 haad 186 1.1 haad int status; /* see DM_THREAD_{RUNNING,SHUTDOWN,DONE} 187 1.1 haad constants above */ 188 1.1 haad enum dm_event_mask events; /* bitfield for event filter. */ 189 1.1 haad enum dm_event_mask current_events; /* bitfield for occured events. */ 190 1.1 haad struct dm_task *current_task; 191 1.1 haad time_t next_time; 192 1.1 haad uint32_t timeout; 193 1.1 haad struct dm_list timeout_list; 194 1.1 haad void *dso_private; /* dso per-thread status variable */ 195 1.1 haad }; 196 1.1 haad static DM_LIST_INIT(_thread_registry); 197 1.1 haad static DM_LIST_INIT(_thread_registry_unused); 198 1.1 haad 199 1.1 haad static int _timeout_running; 200 1.1 haad static DM_LIST_INIT(_timeout_registry); 201 1.1 haad static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER; 202 1.1 haad static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER; 203 1.1 haad 204 1.1 haad static void _debuglog(const char *fmt, ...) 205 1.1 haad { 206 1.1 haad time_t P; 207 1.1 haad va_list ap; 208 1.1 haad 209 1.1 haad if (!_debug) 210 1.1 haad return; 211 1.1 haad 212 1.1 haad va_start(ap,fmt); 213 1.1 haad 214 1.1 haad time(&P); 215 1.1 haad fprintf(stderr, "dmeventd[%p]: %.15s ", (void *) pthread_self(), ctime(&P)+4 ); 216 1.1 haad vfprintf(stderr, fmt, ap); 217 1.1 haad fprintf(stderr, "\n"); 218 1.1 haad 219 1.1 haad va_end(ap); 220 1.1 haad } 221 1.1 haad 222 1.1 haad /* Allocate/free the status structure for a monitoring thread. */ 223 1.1 haad static struct thread_status *_alloc_thread_status(struct message_data *data, 224 1.1 haad struct dso_data *dso_data) 225 1.1 haad { 226 1.1 haad struct thread_status *ret = (typeof(ret)) dm_malloc(sizeof(*ret)); 227 1.1 haad 228 1.1 haad if (!ret) 229 1.1 haad return NULL; 230 1.1 haad 231 1.1 haad memset(ret, 0, sizeof(*ret)); 232 1.1 haad if (!(ret->device.uuid = dm_strdup(data->device_uuid))) { 233 1.1 haad dm_free(ret); 234 1.1 haad return NULL; 235 1.1 haad } 236 1.1 haad 237 1.1 haad ret->current_task = NULL; 238 1.1 haad ret->device.name = NULL; 239 1.1 haad ret->device.major = ret->device.minor = 0; 240 1.1 haad ret->dso_data = dso_data; 241 1.1 haad ret->events = data->events.field; 242 1.1 haad ret->timeout = data->timeout.secs; 243 1.1 haad dm_list_init(&ret->timeout_list); 244 1.1 haad 245 1.1 haad return ret; 246 1.1 haad } 247 1.1 haad 248 1.1 haad static void _free_thread_status(struct thread_status *thread) 249 1.1 haad { 250 1.1 haad if (thread->current_task) 251 1.1 haad dm_task_destroy(thread->current_task); 252 1.1 haad dm_free(thread->device.uuid); 253 1.1 haad dm_free(thread->device.name); 254 1.1 haad dm_free(thread); 255 1.1 haad } 256 1.1 haad 257 1.1 haad /* Allocate/free DSO data. */ 258 1.1 haad static struct dso_data *_alloc_dso_data(struct message_data *data) 259 1.1 haad { 260 1.1 haad struct dso_data *ret = (typeof(ret)) dm_malloc(sizeof(*ret)); 261 1.1 haad 262 1.1 haad if (!ret) 263 1.1 haad return NULL; 264 1.1 haad 265 1.1 haad memset(ret, 0, sizeof(*ret)); 266 1.1 haad if (!(ret->dso_name = dm_strdup(data->dso_name))) { 267 1.1 haad dm_free(ret); 268 1.1 haad return NULL; 269 1.1 haad } 270 1.1 haad 271 1.1 haad return ret; 272 1.1 haad } 273 1.1 haad 274 1.1 haad /* Create a device monitoring thread. */ 275 1.1 haad static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg) 276 1.1 haad { 277 1.1 haad pthread_attr_t attr; 278 1.1 haad pthread_attr_init(&attr); 279 1.1 haad /* 280 1.1 haad * We use a smaller stack since it gets preallocated in its entirety 281 1.1 haad */ 282 1.1 haad pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE); 283 1.1 haad return pthread_create(t, &attr, fun, arg); 284 1.1 haad } 285 1.1 haad 286 1.1 haad static void _free_dso_data(struct dso_data *data) 287 1.1 haad { 288 1.1 haad dm_free(data->dso_name); 289 1.1 haad dm_free(data); 290 1.1 haad } 291 1.1 haad 292 1.1 haad /* 293 1.1 haad * Fetch a string off src and duplicate it into *ptr. 294 1.1 haad * Pay attention to zero-length strings. 295 1.1 haad */ 296 1.1 haad /* FIXME? move to libdevmapper to share with the client lib (need to 297 1.1 haad make delimiter a parameter then) */ 298 1.1 haad static int _fetch_string(char **ptr, char **src, const int delimiter) 299 1.1 haad { 300 1.1 haad int ret = 0; 301 1.1 haad char *p; 302 1.1 haad size_t len; 303 1.1 haad 304 1.1 haad if ((p = strchr(*src, delimiter))) 305 1.1 haad *p = 0; 306 1.1 haad 307 1.1 haad if ((*ptr = dm_strdup(*src))) { 308 1.1 haad if ((len = strlen(*ptr))) 309 1.1 haad *src += len; 310 1.1 haad else { 311 1.1 haad dm_free(*ptr); 312 1.1 haad *ptr = NULL; 313 1.1 haad } 314 1.1 haad 315 1.1 haad (*src)++; 316 1.1 haad ret = 1; 317 1.1 haad } 318 1.1 haad 319 1.1 haad if (p) 320 1.1 haad *p = delimiter; 321 1.1 haad 322 1.1 haad return ret; 323 1.1 haad } 324 1.1 haad 325 1.1 haad /* Free message memory. */ 326 1.1 haad static void _free_message(struct message_data *message_data) 327 1.1 haad { 328 1.1 haad if (message_data->id) 329 1.1 haad dm_free(message_data->id); 330 1.1 haad if (message_data->dso_name) 331 1.1 haad dm_free(message_data->dso_name); 332 1.1 haad 333 1.1 haad if (message_data->device_uuid) 334 1.1 haad dm_free(message_data->device_uuid); 335 1.1 haad 336 1.1 haad } 337 1.1 haad 338 1.1 haad /* Parse a register message from the client. */ 339 1.1 haad static int _parse_message(struct message_data *message_data) 340 1.1 haad { 341 1.1 haad int ret = 0; 342 1.1 haad char *p = message_data->msg->data; 343 1.1 haad struct dm_event_daemon_message *msg = message_data->msg; 344 1.1 haad 345 1.1 haad if (!msg->data) 346 1.1 haad return 0; 347 1.1 haad 348 1.1 haad /* 349 1.1 haad * Retrieve application identifier, mapped device 350 1.1 haad * path and events # string from message. 351 1.1 haad */ 352 1.1 haad if (_fetch_string(&message_data->id, &p, ' ') && 353 1.1 haad _fetch_string(&message_data->dso_name, &p, ' ') && 354 1.1 haad _fetch_string(&message_data->device_uuid, &p, ' ') && 355 1.1 haad _fetch_string(&message_data->events.str, &p, ' ') && 356 1.1 haad _fetch_string(&message_data->timeout.str, &p, ' ')) { 357 1.1 haad if (message_data->events.str) { 358 1.1 haad enum dm_event_mask i = atoi(message_data->events.str); 359 1.1 haad 360 1.1 haad /* 361 1.1 haad * Free string representaion of events. 362 1.1 haad * Not needed an more. 363 1.1 haad */ 364 1.1 haad dm_free(message_data->events.str); 365 1.1 haad message_data->events.field = i; 366 1.1 haad } 367 1.1 haad if (message_data->timeout.str) { 368 1.1 haad uint32_t secs = atoi(message_data->timeout.str); 369 1.1 haad dm_free(message_data->timeout.str); 370 1.1 haad message_data->timeout.secs = secs ? secs : 371 1.1 haad DM_EVENT_DEFAULT_TIMEOUT; 372 1.1 haad } 373 1.1 haad 374 1.1 haad ret = 1; 375 1.1 haad } 376 1.1 haad 377 1.1 haad dm_free(msg->data); 378 1.1 haad msg->data = NULL; 379 1.1 haad msg->size = 0; 380 1.1 haad return ret; 381 1.1 haad }; 382 1.1 haad 383 1.1 haad /* Global mutex to lock access to lists et al. See _global_mutex 384 1.1 haad above. */ 385 1.1 haad static int _lock_mutex(void) 386 1.1 haad { 387 1.1 haad return pthread_mutex_lock(&_global_mutex); 388 1.1 haad } 389 1.1 haad 390 1.1 haad static int _unlock_mutex(void) 391 1.1 haad { 392 1.1 haad return pthread_mutex_unlock(&_global_mutex); 393 1.1 haad } 394 1.1 haad 395 1.1 haad /* Store pid in pidfile. */ 396 1.1 haad static int _storepid(int lf) 397 1.1 haad { 398 1.1 haad int len; 399 1.1 haad char pid[8]; 400 1.1 haad 401 1.1 haad if ((len = snprintf(pid, sizeof(pid), "%u\n", getpid())) < 0) 402 1.1 haad return 0; 403 1.1 haad 404 1.1 haad if (len > (int) sizeof(pid)) 405 1.1 haad len = (int) sizeof(pid); 406 1.1 haad 407 1.1 haad if (write(lf, pid, (size_t) len) != len) 408 1.1 haad return 0; 409 1.1 haad 410 1.1 haad fsync(lf); 411 1.1 haad 412 1.1 haad return 1; 413 1.1 haad } 414 1.1 haad 415 1.1 haad /* Check, if a device exists. */ 416 1.1 haad static int _fill_device_data(struct thread_status *ts) 417 1.1 haad { 418 1.1 haad struct dm_task *dmt; 419 1.1 haad struct dm_info dmi; 420 1.1 haad 421 1.1 haad if (!ts->device.uuid) 422 1.1 haad return 0; 423 1.1 haad 424 1.1 haad ts->device.name = NULL; 425 1.1 haad ts->device.major = ts->device.minor = 0; 426 1.1 haad 427 1.1 haad dmt = dm_task_create(DM_DEVICE_INFO); 428 1.1 haad if (!dmt) 429 1.1 haad return 0; 430 1.1 haad 431 1.1 haad dm_task_set_uuid(dmt, ts->device.uuid); 432 1.1 haad if (!dm_task_run(dmt)) 433 1.1 haad goto fail; 434 1.1 haad 435 1.1 haad ts->device.name = dm_strdup(dm_task_get_name(dmt)); 436 1.1 haad if (!ts->device.name) 437 1.1 haad goto fail; 438 1.1 haad 439 1.1 haad if (!dm_task_get_info(dmt, &dmi)) 440 1.1 haad goto fail; 441 1.1 haad 442 1.1 haad ts->device.major = dmi.major; 443 1.1 haad ts->device.minor = dmi.minor; 444 1.1 haad 445 1.1 haad dm_task_destroy(dmt); 446 1.1 haad return 1; 447 1.1 haad 448 1.1 haad fail: 449 1.1 haad dm_task_destroy(dmt); 450 1.1 haad dm_free(ts->device.name); 451 1.1 haad return 0; 452 1.1 haad } 453 1.1 haad 454 1.1 haad /* 455 1.1 haad * Find an existing thread for a device. 456 1.1 haad * 457 1.1 haad * Mutex must be held when calling this. 458 1.1 haad */ 459 1.1 haad static struct thread_status *_lookup_thread_status(struct message_data *data) 460 1.1 haad { 461 1.1 haad struct thread_status *thread; 462 1.1 haad 463 1.1 haad dm_list_iterate_items(thread, &_thread_registry) 464 1.1 haad if (!strcmp(data->device_uuid, thread->device.uuid)) 465 1.1 haad return thread; 466 1.1 haad 467 1.1 haad return NULL; 468 1.1 haad } 469 1.1 haad 470 1.1 haad /* Cleanup at exit. */ 471 1.1 haad static void _exit_dm_lib(void) 472 1.1 haad { 473 1.1 haad dm_lib_release(); 474 1.1 haad dm_lib_exit(); 475 1.1 haad } 476 1.1 haad 477 1.1 haad static void _exit_timeout(void *unused __attribute((unused))) 478 1.1 haad { 479 1.1 haad _timeout_running = 0; 480 1.1 haad pthread_mutex_unlock(&_timeout_mutex); 481 1.1 haad } 482 1.1 haad 483 1.1 haad /* Wake up monitor threads every so often. */ 484 1.1 haad static void *_timeout_thread(void *unused __attribute((unused))) 485 1.1 haad { 486 1.1 haad struct timespec timeout; 487 1.1 haad time_t curr_time; 488 1.1 haad 489 1.1 haad timeout.tv_nsec = 0; 490 1.1 haad pthread_cleanup_push(_exit_timeout, NULL); 491 1.1 haad pthread_mutex_lock(&_timeout_mutex); 492 1.1 haad 493 1.1 haad while (!dm_list_empty(&_timeout_registry)) { 494 1.1 haad struct thread_status *thread; 495 1.1 haad 496 1.1 haad timeout.tv_sec = 0; 497 1.1 haad curr_time = time(NULL); 498 1.1 haad 499 1.1 haad dm_list_iterate_items_gen(thread, &_timeout_registry, timeout_list) { 500 1.1 haad if (thread->next_time <= curr_time) { 501 1.1 haad thread->next_time = curr_time + thread->timeout; 502 1.1 haad pthread_kill(thread->thread, SIGALRM); 503 1.1 haad } 504 1.1 haad 505 1.1 haad if (thread->next_time < timeout.tv_sec || !timeout.tv_sec) 506 1.1 haad timeout.tv_sec = thread->next_time; 507 1.1 haad } 508 1.1 haad 509 1.1 haad pthread_cond_timedwait(&_timeout_cond, &_timeout_mutex, 510 1.1 haad &timeout); 511 1.1 haad } 512 1.1 haad 513 1.1 haad pthread_cleanup_pop(1); 514 1.1 haad 515 1.1 haad return NULL; 516 1.1 haad } 517 1.1 haad 518 1.1 haad static int _register_for_timeout(struct thread_status *thread) 519 1.1 haad { 520 1.1 haad int ret = 0; 521 1.1 haad 522 1.1 haad pthread_mutex_lock(&_timeout_mutex); 523 1.1 haad 524 1.1 haad thread->next_time = time(NULL) + thread->timeout; 525 1.1 haad 526 1.1 haad if (dm_list_empty(&thread->timeout_list)) { 527 1.1 haad dm_list_add(&_timeout_registry, &thread->timeout_list); 528 1.1 haad if (_timeout_running) 529 1.1 haad pthread_cond_signal(&_timeout_cond); 530 1.1 haad } 531 1.1 haad 532 1.1 haad if (!_timeout_running) { 533 1.1 haad pthread_t timeout_id; 534 1.1 haad 535 1.1 haad if (!(ret = -_pthread_create_smallstack(&timeout_id, _timeout_thread, NULL))) 536 1.1 haad _timeout_running = 1; 537 1.1 haad } 538 1.1 haad 539 1.1 haad pthread_mutex_unlock(&_timeout_mutex); 540 1.1 haad 541 1.1 haad return ret; 542 1.1 haad } 543 1.1 haad 544 1.1 haad static void _unregister_for_timeout(struct thread_status *thread) 545 1.1 haad { 546 1.1 haad pthread_mutex_lock(&_timeout_mutex); 547 1.1 haad if (!dm_list_empty(&thread->timeout_list)) { 548 1.1 haad dm_list_del(&thread->timeout_list); 549 1.1 haad dm_list_init(&thread->timeout_list); 550 1.1 haad } 551 1.1 haad pthread_mutex_unlock(&_timeout_mutex); 552 1.1 haad } 553 1.1 haad 554 1.1 haad static void _no_intr_log(int level, const char *file, int line, 555 1.1 haad const char *f, ...) 556 1.1 haad { 557 1.1 haad va_list ap; 558 1.1 haad 559 1.1 haad if (errno == EINTR) 560 1.1 haad return; 561 1.1 haad if (level > _LOG_WARN) 562 1.1 haad return; 563 1.1 haad 564 1.1 haad va_start(ap, f); 565 1.1 haad 566 1.1 haad if (level < _LOG_WARN) 567 1.1 haad vfprintf(stderr, f, ap); 568 1.1 haad else 569 1.1 haad vprintf(f, ap); 570 1.1 haad 571 1.1 haad va_end(ap); 572 1.1 haad 573 1.1 haad if (level < _LOG_WARN) 574 1.1 haad fprintf(stderr, "\n"); 575 1.1 haad else 576 1.1 haad fprintf(stdout, "\n"); 577 1.1 haad } 578 1.1 haad 579 1.1 haad static sigset_t _unblock_sigalrm(void) 580 1.1 haad { 581 1.1 haad sigset_t set, old; 582 1.1 haad 583 1.1 haad sigemptyset(&set); 584 1.1 haad sigaddset(&set, SIGALRM); 585 1.1 haad pthread_sigmask(SIG_UNBLOCK, &set, &old); 586 1.1 haad return old; 587 1.1 haad } 588 1.1 haad 589 1.1 haad #define DM_WAIT_RETRY 0 590 1.1 haad #define DM_WAIT_INTR 1 591 1.1 haad #define DM_WAIT_FATAL 2 592 1.1 haad 593 1.1 haad /* Wait on a device until an event occurs. */ 594 1.1 haad static int _event_wait(struct thread_status *thread, struct dm_task **task) 595 1.1 haad { 596 1.1 haad sigset_t set; 597 1.1 haad int ret = DM_WAIT_RETRY; 598 1.1 haad struct dm_task *dmt; 599 1.1 haad struct dm_info info; 600 1.1 haad 601 1.1 haad *task = 0; 602 1.1 haad 603 1.1 haad if (!(dmt = dm_task_create(DM_DEVICE_WAITEVENT))) 604 1.1 haad return DM_WAIT_RETRY; 605 1.1 haad 606 1.1 haad thread->current_task = dmt; 607 1.1 haad 608 1.1 haad if (!dm_task_set_uuid(dmt, thread->device.uuid) || 609 1.1 haad !dm_task_set_event_nr(dmt, thread->event_nr)) 610 1.1 haad goto out; 611 1.1 haad 612 1.1 haad /* 613 1.1 haad * This is so that you can break out of waiting on an event, 614 1.1 haad * either for a timeout event, or to cancel the thread. 615 1.1 haad */ 616 1.1 haad set = _unblock_sigalrm(); 617 1.1 haad dm_log_init(_no_intr_log); 618 1.1 haad errno = 0; 619 1.1 haad if (dm_task_run(dmt)) { 620 1.1 haad thread->current_events |= DM_EVENT_DEVICE_ERROR; 621 1.1 haad ret = DM_WAIT_INTR; 622 1.1 haad 623 1.1 haad if ((ret = dm_task_get_info(dmt, &info))) 624 1.1 haad thread->event_nr = info.event_nr; 625 1.1 haad } else if (thread->events & DM_EVENT_TIMEOUT && errno == EINTR) { 626 1.1 haad thread->current_events |= DM_EVENT_TIMEOUT; 627 1.1 haad ret = DM_WAIT_INTR; 628 1.1 haad } else if (thread->status == DM_THREAD_SHUTDOWN && errno == EINTR) { 629 1.1 haad ret = DM_WAIT_FATAL; 630 1.1 haad } else { 631 1.1 haad syslog(LOG_NOTICE, "dm_task_run failed, errno = %d, %s", 632 1.1 haad errno, strerror(errno)); 633 1.1 haad if (errno == ENXIO) { 634 1.1 haad syslog(LOG_ERR, "%s disappeared, detaching", 635 1.1 haad thread->device.name); 636 1.1 haad ret = DM_WAIT_FATAL; 637 1.1 haad } 638 1.1 haad } 639 1.1 haad 640 1.1 haad pthread_sigmask(SIG_SETMASK, &set, NULL); 641 1.1 haad dm_log_init(NULL); 642 1.1 haad 643 1.1 haad out: 644 1.1 haad if (ret == DM_WAIT_FATAL || ret == DM_WAIT_RETRY) { 645 1.1 haad dm_task_destroy(dmt); 646 1.1 haad thread->current_task = NULL; 647 1.1 haad } else 648 1.1 haad *task = dmt; 649 1.1 haad 650 1.1 haad return ret; 651 1.1 haad } 652 1.1 haad 653 1.1 haad /* Register a device with the DSO. */ 654 1.1 haad static int _do_register_device(struct thread_status *thread) 655 1.1 haad { 656 1.1 haad return thread->dso_data->register_device(thread->device.name, 657 1.1 haad thread->device.uuid, 658 1.1 haad thread->device.major, 659 1.1 haad thread->device.minor, 660 1.1 haad &(thread->dso_private)); 661 1.1 haad } 662 1.1 haad 663 1.1 haad /* Unregister a device with the DSO. */ 664 1.1 haad static int _do_unregister_device(struct thread_status *thread) 665 1.1 haad { 666 1.1 haad return thread->dso_data->unregister_device(thread->device.name, 667 1.1 haad thread->device.uuid, 668 1.1 haad thread->device.major, 669 1.1 haad thread->device.minor, 670 1.1 haad &(thread->dso_private)); 671 1.1 haad } 672 1.1 haad 673 1.1 haad /* Process an event in the DSO. */ 674 1.1 haad static void _do_process_event(struct thread_status *thread, struct dm_task *task) 675 1.1 haad { 676 1.1 haad thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private)); 677 1.1 haad } 678 1.1 haad 679 1.1 haad /* Thread cleanup handler to unregister device. */ 680 1.1 haad static void _monitor_unregister(void *arg) 681 1.1 haad { 682 1.1 haad struct thread_status *thread = arg, *thread_iter; 683 1.1 haad 684 1.1 haad if (!_do_unregister_device(thread)) 685 1.1 haad syslog(LOG_ERR, "%s: %s unregister failed\n", __func__, 686 1.1 haad thread->device.name); 687 1.1 haad if (thread->current_task) 688 1.1 haad dm_task_destroy(thread->current_task); 689 1.1 haad thread->current_task = NULL; 690 1.1 haad 691 1.1 haad _lock_mutex(); 692 1.1 haad if (thread->events & DM_EVENT_TIMEOUT) { 693 1.1 haad /* _unregister_for_timeout locks another mutex, we 694 1.1 haad don't want to deadlock so we release our mutex for 695 1.1 haad a bit */ 696 1.1 haad _unlock_mutex(); 697 1.1 haad _unregister_for_timeout(thread); 698 1.1 haad _lock_mutex(); 699 1.1 haad } 700 1.1 haad /* we may have been relinked to unused registry since we were 701 1.1 haad called, so check that */ 702 1.1 haad dm_list_iterate_items(thread_iter, &_thread_registry_unused) 703 1.1 haad if (thread_iter == thread) { 704 1.1 haad thread->status = DM_THREAD_DONE; 705 1.1 haad _unlock_mutex(); 706 1.1 haad return; 707 1.1 haad } 708 1.1 haad thread->status = DM_THREAD_DONE; 709 1.1 haad UNLINK_THREAD(thread); 710 1.1 haad LINK(thread, &_thread_registry_unused); 711 1.1 haad _unlock_mutex(); 712 1.1 haad } 713 1.1 haad 714 1.1 haad static struct dm_task *_get_device_status(struct thread_status *ts) 715 1.1 haad { 716 1.1 haad struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS); 717 1.1 haad 718 1.1 haad if (!dmt) 719 1.1 haad return NULL; 720 1.1 haad 721 1.1 haad dm_task_set_uuid(dmt, ts->device.uuid); 722 1.1 haad 723 1.1 haad if (!dm_task_run(dmt)) { 724 1.1 haad dm_task_destroy(dmt); 725 1.1 haad return NULL; 726 1.1 haad } 727 1.1 haad 728 1.1 haad return dmt; 729 1.1 haad } 730 1.1 haad 731 1.1 haad /* Device monitoring thread. */ 732 1.1 haad static void *_monitor_thread(void *arg) 733 1.1 haad { 734 1.1 haad struct thread_status *thread = arg; 735 1.1 haad int wait_error = 0; 736 1.1 haad struct dm_task *task; 737 1.1 haad 738 1.1 haad pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); 739 1.1 haad pthread_cleanup_push(_monitor_unregister, thread); 740 1.1 haad 741 1.1 haad /* Wait for do_process_request() to finish its task. */ 742 1.1 haad _lock_mutex(); 743 1.1 haad thread->status = DM_THREAD_RUNNING; 744 1.1 haad _unlock_mutex(); 745 1.1 haad 746 1.1 haad /* Loop forever awaiting/analyzing device events. */ 747 1.1 haad while (1) { 748 1.1 haad thread->current_events = 0; 749 1.1 haad 750 1.1 haad wait_error = _event_wait(thread, &task); 751 1.1 haad if (wait_error == DM_WAIT_RETRY) 752 1.1 haad continue; 753 1.1 haad 754 1.1 haad if (wait_error == DM_WAIT_FATAL) 755 1.1 haad break; 756 1.1 haad 757 1.1 haad /* Timeout occurred, task is not filled properly. 758 1.1 haad * We get device status here for processing it in DSO. 759 1.1 haad */ 760 1.1 haad if (wait_error == DM_WAIT_INTR && 761 1.1 haad thread->current_events & DM_EVENT_TIMEOUT) { 762 1.1 haad dm_task_destroy(task); 763 1.1 haad task = _get_device_status(thread); 764 1.1 haad /* FIXME: syslog fail here ? */ 765 1.1 haad if (!(thread->current_task = task)) 766 1.1 haad continue; 767 1.1 haad } 768 1.1 haad 769 1.1 haad /* 770 1.1 haad * We know that wait succeeded and stored a 771 1.1 haad * pointer to dm_task with device status into task. 772 1.1 haad */ 773 1.1 haad 774 1.1 haad /* 775 1.1 haad * Check against filter. 776 1.1 haad * 777 1.1 haad * If there's current events delivered from _event_wait() AND 778 1.1 haad * the device got registered for those events AND 779 1.1 haad * those events haven't been processed yet, call 780 1.1 haad * the DSO's process_event() handler. 781 1.1 haad */ 782 1.1 haad _lock_mutex(); 783 1.1 haad if (thread->status == DM_THREAD_SHUTDOWN) { 784 1.1 haad _unlock_mutex(); 785 1.1 haad break; 786 1.1 haad } 787 1.1 haad _unlock_mutex(); 788 1.1 haad 789 1.1 haad if (thread->events & thread->current_events) { 790 1.1 haad _lock_mutex(); 791 1.1 haad thread->processing = 1; 792 1.1 haad _unlock_mutex(); 793 1.1 haad 794 1.1 haad _do_process_event(thread, task); 795 1.1 haad dm_task_destroy(task); 796 1.1 haad thread->current_task = NULL; 797 1.1 haad 798 1.1 haad _lock_mutex(); 799 1.1 haad thread->processing = 0; 800 1.1 haad _unlock_mutex(); 801 1.1 haad } else { 802 1.1 haad dm_task_destroy(task); 803 1.1 haad thread->current_task = NULL; 804 1.1 haad } 805 1.1 haad } 806 1.1 haad 807 1.1 haad pthread_cleanup_pop(1); 808 1.1 haad 809 1.1 haad return NULL; 810 1.1 haad } 811 1.1 haad 812 1.1 haad /* Create a device monitoring thread. */ 813 1.1 haad static int _create_thread(struct thread_status *thread) 814 1.1 haad { 815 1.1 haad return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread); 816 1.1 haad } 817 1.1 haad 818 1.1 haad static int _terminate_thread(struct thread_status *thread) 819 1.1 haad { 820 1.1 haad return pthread_kill(thread->thread, SIGALRM); 821 1.1 haad } 822 1.1 haad 823 1.1 haad /* DSO reference counting. Call with _global_mutex locked! */ 824 1.1 haad static void _lib_get(struct dso_data *data) 825 1.1 haad { 826 1.1 haad data->ref_count++; 827 1.1 haad } 828 1.1 haad 829 1.1 haad static void _lib_put(struct dso_data *data) 830 1.1 haad { 831 1.1 haad if (!--data->ref_count) { 832 1.1 haad dlclose(data->dso_handle); 833 1.1 haad UNLINK_DSO(data); 834 1.1 haad _free_dso_data(data); 835 1.1 haad } 836 1.1 haad } 837 1.1 haad 838 1.1 haad /* Find DSO data. */ 839 1.1 haad static struct dso_data *_lookup_dso(struct message_data *data) 840 1.1 haad { 841 1.1 haad struct dso_data *dso_data, *ret = NULL; 842 1.1 haad 843 1.1 haad dm_list_iterate_items(dso_data, &_dso_registry) 844 1.1 haad if (!strcmp(data->dso_name, dso_data->dso_name)) { 845 1.1 haad _lib_get(dso_data); 846 1.1 haad ret = dso_data; 847 1.1 haad break; 848 1.1 haad } 849 1.1 haad 850 1.1 haad return ret; 851 1.1 haad } 852 1.1 haad 853 1.1 haad /* Lookup DSO symbols we need. */ 854 1.1 haad static int _lookup_symbol(void *dl, void **symbol, const char *name) 855 1.1 haad { 856 1.1 haad if ((*symbol = dlsym(dl, name))) 857 1.1 haad return 1; 858 1.1 haad 859 1.1 haad return 0; 860 1.1 haad } 861 1.1 haad 862 1.1 haad static int lookup_symbols(void *dl, struct dso_data *data) 863 1.1 haad { 864 1.1 haad return _lookup_symbol(dl, (void *) &data->process_event, 865 1.1 haad "process_event") && 866 1.1 haad _lookup_symbol(dl, (void *) &data->register_device, 867 1.1 haad "register_device") && 868 1.1 haad _lookup_symbol(dl, (void *) &data->unregister_device, 869 1.1 haad "unregister_device"); 870 1.1 haad } 871 1.1 haad 872 1.1 haad /* Load an application specific DSO. */ 873 1.1 haad static struct dso_data *_load_dso(struct message_data *data) 874 1.1 haad { 875 1.1 haad void *dl; 876 1.1 haad struct dso_data *ret = NULL; 877 1.1 haad 878 1.1 haad if (!(dl = dlopen(data->dso_name, RTLD_NOW))) { 879 1.1 haad const char *dlerr = dlerror(); 880 1.1 haad syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name, 881 1.1 haad dlerr); 882 1.1 haad data->msg->size = 883 1.1 haad dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s", 884 1.1 haad data->id, data->dso_name, dlerr); 885 1.1 haad return NULL; 886 1.1 haad } 887 1.1 haad 888 1.1 haad if (!(ret = _alloc_dso_data(data))) { 889 1.1 haad dlclose(dl); 890 1.1 haad return NULL; 891 1.1 haad } 892 1.1 haad 893 1.1 haad if (!(lookup_symbols(dl, ret))) { 894 1.1 haad _free_dso_data(ret); 895 1.1 haad dlclose(dl); 896 1.1 haad return NULL; 897 1.1 haad } 898 1.1 haad 899 1.1 haad /* 900 1.1 haad * Keep handle to close the library once 901 1.1 haad * we've got no references to it any more. 902 1.1 haad */ 903 1.1 haad ret->dso_handle = dl; 904 1.1 haad _lib_get(ret); 905 1.1 haad 906 1.1 haad _lock_mutex(); 907 1.1 haad LINK_DSO(ret); 908 1.1 haad _unlock_mutex(); 909 1.1 haad 910 1.1 haad return ret; 911 1.1 haad } 912 1.1 haad 913 1.1 haad /* Return success on daemon active check. */ 914 1.1 haad static int _active(struct message_data *message_data) 915 1.1 haad { 916 1.1 haad return 0; 917 1.1 haad } 918 1.1 haad 919 1.1 haad /* 920 1.1 haad * Register for an event. 921 1.1 haad * 922 1.1 haad * Only one caller at a time here, because we use 923 1.1 haad * a FIFO and lock it against multiple accesses. 924 1.1 haad */ 925 1.1 haad static int _register_for_event(struct message_data *message_data) 926 1.1 haad { 927 1.1 haad int ret = 0; 928 1.1 haad struct thread_status *thread, *thread_new = NULL; 929 1.1 haad struct dso_data *dso_data; 930 1.1 haad 931 1.1 haad if (!(dso_data = _lookup_dso(message_data)) && 932 1.1 haad !(dso_data = _load_dso(message_data))) { 933 1.1 haad stack; 934 1.1 haad #ifdef ELIBACC 935 1.1 haad ret = -ELIBACC; 936 1.1 haad #else 937 1.1 haad ret = -ENODEV; 938 1.1 haad #endif 939 1.1 haad goto out; 940 1.1 haad } 941 1.1 haad 942 1.1 haad /* Preallocate thread status struct to avoid deadlock. */ 943 1.1 haad if (!(thread_new = _alloc_thread_status(message_data, dso_data))) { 944 1.1 haad stack; 945 1.1 haad ret = -ENOMEM; 946 1.1 haad goto out; 947 1.1 haad } 948 1.1 haad 949 1.1 haad if (!_fill_device_data(thread_new)) { 950 1.1 haad stack; 951 1.1 haad ret = -ENODEV; 952 1.1 haad goto out; 953 1.1 haad } 954 1.1 haad 955 1.1 haad _lock_mutex(); 956 1.1 haad 957 1.1 haad /* If creation of timeout thread fails (as it may), we fail 958 1.1 haad here completely. The client is responsible for either 959 1.1 haad retrying later or trying to register without timeout 960 1.1 haad events. However, if timeout thread cannot be started, it 961 1.1 haad usually means we are so starved on resources that we are 962 1.1 haad almost as good as dead already... */ 963 1.1 haad if (thread_new->events & DM_EVENT_TIMEOUT) { 964 1.1 haad ret = -_register_for_timeout(thread_new); 965 1.1 haad if (ret) { 966 1.1 haad _unlock_mutex(); 967 1.1 haad goto out; 968 1.1 haad } 969 1.1 haad } 970 1.1 haad 971 1.1 haad if (!(thread = _lookup_thread_status(message_data))) { 972 1.1 haad _unlock_mutex(); 973 1.1 haad 974 1.1 haad if (!(ret = _do_register_device(thread_new))) 975 1.1 haad goto out; 976 1.1 haad 977 1.1 haad thread = thread_new; 978 1.1 haad thread_new = NULL; 979 1.1 haad 980 1.1 haad /* Try to create the monitoring thread for this device. */ 981 1.1 haad _lock_mutex(); 982 1.1 haad if ((ret = -_create_thread(thread))) { 983 1.1 haad _unlock_mutex(); 984 1.1 haad _do_unregister_device(thread); 985 1.1 haad _free_thread_status(thread); 986 1.1 haad goto out; 987 1.1 haad } else 988 1.1 haad LINK_THREAD(thread); 989 1.1 haad } 990 1.1 haad 991 1.1 haad /* Or event # into events bitfield. */ 992 1.1 haad thread->events |= message_data->events.field; 993 1.1 haad 994 1.1 haad _unlock_mutex(); 995 1.1 haad 996 1.1 haad out: 997 1.1 haad /* 998 1.1 haad * Deallocate thread status after releasing 999 1.1 haad * the lock in case we haven't used it. 1000 1.1 haad */ 1001 1.1 haad if (thread_new) 1002 1.1 haad _free_thread_status(thread_new); 1003 1.1 haad 1004 1.1 haad return ret; 1005 1.1 haad } 1006 1.1 haad 1007 1.1 haad /* 1008 1.1 haad * Unregister for an event. 1009 1.1 haad * 1010 1.1 haad * Only one caller at a time here as with register_for_event(). 1011 1.1 haad */ 1012 1.1 haad static int _unregister_for_event(struct message_data *message_data) 1013 1.1 haad { 1014 1.1 haad int ret = 0; 1015 1.1 haad struct thread_status *thread; 1016 1.1 haad 1017 1.1 haad /* 1018 1.1 haad * Clear event in bitfield and deactivate 1019 1.1 haad * monitoring thread in case bitfield is 0. 1020 1.1 haad */ 1021 1.1 haad _lock_mutex(); 1022 1.1 haad 1023 1.1 haad if (!(thread = _lookup_thread_status(message_data))) { 1024 1.1 haad _unlock_mutex(); 1025 1.1 haad ret = -ENODEV; 1026 1.1 haad goto out; 1027 1.1 haad } 1028 1.1 haad 1029 1.1 haad if (thread->status == DM_THREAD_DONE) { 1030 1.1 haad /* the thread has terminated while we were not 1031 1.1 haad watching */ 1032 1.1 haad _unlock_mutex(); 1033 1.1 haad return 0; 1034 1.1 haad } 1035 1.1 haad 1036 1.1 haad thread->events &= ~message_data->events.field; 1037 1.1 haad 1038 1.1 haad if (!(thread->events & DM_EVENT_TIMEOUT)) 1039 1.1 haad _unregister_for_timeout(thread); 1040 1.1 haad /* 1041 1.1 haad * In case there's no events to monitor on this device -> 1042 1.1 haad * unlink and terminate its monitoring thread. 1043 1.1 haad */ 1044 1.1 haad if (!thread->events) { 1045 1.1 haad UNLINK_THREAD(thread); 1046 1.1 haad LINK(thread, &_thread_registry_unused); 1047 1.1 haad } 1048 1.1 haad _unlock_mutex(); 1049 1.1 haad 1050 1.1 haad out: 1051 1.1 haad return ret; 1052 1.1 haad } 1053 1.1 haad 1054 1.1 haad /* 1055 1.1 haad * Get registered device. 1056 1.1 haad * 1057 1.1 haad * Only one caller at a time here as with register_for_event(). 1058 1.1 haad */ 1059 1.1 haad static int _registered_device(struct message_data *message_data, 1060 1.1 haad struct thread_status *thread) 1061 1.1 haad { 1062 1.1 haad struct dm_event_daemon_message *msg = message_data->msg; 1063 1.1 haad 1064 1.1 haad const char *fmt = "%s %s %s %u"; 1065 1.1 haad const char *id = message_data->id; 1066 1.1 haad const char *dso = thread->dso_data->dso_name; 1067 1.1 haad const char *dev = thread->device.uuid; 1068 1.1 haad unsigned events = ((thread->status == DM_THREAD_RUNNING) 1069 1.1 haad && (thread->events)) ? thread->events : thread-> 1070 1.1 haad events | DM_EVENT_REGISTRATION_PENDING; 1071 1.1 haad 1072 1.1 haad if (msg->data) 1073 1.1 haad dm_free(msg->data); 1074 1.1 haad 1075 1.1 haad msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events); 1076 1.1 haad 1077 1.1 haad _unlock_mutex(); 1078 1.1 haad 1079 1.1 haad return 0; 1080 1.1 haad } 1081 1.1 haad 1082 1.1 haad static int _want_registered_device(char *dso_name, char *device_uuid, 1083 1.1 haad struct thread_status *thread) 1084 1.1 haad { 1085 1.1 haad /* If DSO names and device paths are equal. */ 1086 1.1 haad if (dso_name && device_uuid) 1087 1.1 haad return !strcmp(dso_name, thread->dso_data->dso_name) && 1088 1.1 haad !strcmp(device_uuid, thread->device.uuid) && 1089 1.1 haad (thread->status == DM_THREAD_RUNNING || 1090 1.1 haad (thread->events & DM_EVENT_REGISTRATION_PENDING)); 1091 1.1 haad 1092 1.1 haad /* If DSO names are equal. */ 1093 1.1 haad if (dso_name) 1094 1.1 haad return !strcmp(dso_name, thread->dso_data->dso_name) && 1095 1.1 haad (thread->status == DM_THREAD_RUNNING || 1096 1.1 haad (thread->events & DM_EVENT_REGISTRATION_PENDING)); 1097 1.1 haad 1098 1.1 haad /* If device paths are equal. */ 1099 1.1 haad if (device_uuid) 1100 1.1 haad return !strcmp(device_uuid, thread->device.uuid) && 1101 1.1 haad (thread->status == DM_THREAD_RUNNING || 1102 1.1 haad (thread->events & DM_EVENT_REGISTRATION_PENDING)); 1103 1.1 haad 1104 1.1 haad return 1; 1105 1.1 haad } 1106 1.1 haad 1107 1.1 haad static int _get_registered_dev(struct message_data *message_data, int next) 1108 1.1 haad { 1109 1.1 haad struct thread_status *thread, *hit = NULL; 1110 1.1 haad 1111 1.1 haad _lock_mutex(); 1112 1.1 haad 1113 1.1 haad /* Iterate list of threads checking if we want a particular one. */ 1114 1.1 haad dm_list_iterate_items(thread, &_thread_registry) 1115 1.1 haad if (_want_registered_device(message_data->dso_name, 1116 1.1 haad message_data->device_uuid, 1117 1.1 haad thread)) { 1118 1.1 haad hit = thread; 1119 1.1 haad break; 1120 1.1 haad } 1121 1.1 haad 1122 1.1 haad /* 1123 1.1 haad * If we got a registered device and want the next one -> 1124 1.1 haad * fetch next conforming element off the list. 1125 1.1 haad */ 1126 1.1 haad if (hit && !next) { 1127 1.1 haad _unlock_mutex(); 1128 1.1 haad return _registered_device(message_data, hit); 1129 1.1 haad } 1130 1.1 haad 1131 1.1 haad if (!hit) 1132 1.1 haad goto out; 1133 1.1 haad 1134 1.1 haad thread = hit; 1135 1.1 haad 1136 1.1 haad while (1) { 1137 1.1 haad if (dm_list_end(&_thread_registry, &thread->list)) 1138 1.1 haad goto out; 1139 1.1 haad 1140 1.1 haad thread = dm_list_item(thread->list.n, struct thread_status); 1141 1.1 haad if (_want_registered_device(message_data->dso_name, NULL, thread)) { 1142 1.1 haad hit = thread; 1143 1.1 haad break; 1144 1.1 haad } 1145 1.1 haad } 1146 1.1 haad 1147 1.1 haad _unlock_mutex(); 1148 1.1 haad return _registered_device(message_data, hit); 1149 1.1 haad 1150 1.1 haad out: 1151 1.1 haad _unlock_mutex(); 1152 1.1 haad 1153 1.1 haad return -ENOENT; 1154 1.1 haad } 1155 1.1 haad 1156 1.1 haad static int _get_registered_device(struct message_data *message_data) 1157 1.1 haad { 1158 1.1 haad return _get_registered_dev(message_data, 0); 1159 1.1 haad } 1160 1.1 haad 1161 1.1 haad static int _get_next_registered_device(struct message_data *message_data) 1162 1.1 haad { 1163 1.1 haad return _get_registered_dev(message_data, 1); 1164 1.1 haad } 1165 1.1 haad 1166 1.1 haad static int _set_timeout(struct message_data *message_data) 1167 1.1 haad { 1168 1.1 haad struct thread_status *thread; 1169 1.1 haad 1170 1.1 haad _lock_mutex(); 1171 1.1 haad if ((thread = _lookup_thread_status(message_data))) 1172 1.1 haad thread->timeout = message_data->timeout.secs; 1173 1.1 haad _unlock_mutex(); 1174 1.1 haad 1175 1.1 haad return thread ? 0 : -ENODEV; 1176 1.1 haad } 1177 1.1 haad 1178 1.1 haad static int _get_timeout(struct message_data *message_data) 1179 1.1 haad { 1180 1.1 haad struct thread_status *thread; 1181 1.1 haad struct dm_event_daemon_message *msg = message_data->msg; 1182 1.1 haad 1183 1.1 haad if (msg->data) 1184 1.1 haad dm_free(msg->data); 1185 1.1 haad 1186 1.1 haad _lock_mutex(); 1187 1.1 haad if ((thread = _lookup_thread_status(message_data))) { 1188 1.1 haad msg->size = 1189 1.1 haad dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id, 1190 1.1 haad thread->timeout); 1191 1.1 haad } else { 1192 1.1 haad msg->data = NULL; 1193 1.1 haad msg->size = 0; 1194 1.1 haad } 1195 1.1 haad _unlock_mutex(); 1196 1.1 haad 1197 1.1 haad return thread ? 0 : -ENODEV; 1198 1.1 haad } 1199 1.1 haad 1200 1.1 haad /* Initialize a fifos structure with path names. */ 1201 1.1 haad static void _init_fifos(struct dm_event_fifos *fifos) 1202 1.1 haad { 1203 1.1 haad memset(fifos, 0, sizeof(*fifos)); 1204 1.1 haad 1205 1.1 haad fifos->client_path = DM_EVENT_FIFO_CLIENT; 1206 1.1 haad fifos->server_path = DM_EVENT_FIFO_SERVER; 1207 1.1 haad } 1208 1.1 haad 1209 1.1 haad /* Open fifos used for client communication. */ 1210 1.1 haad static int _open_fifos(struct dm_event_fifos *fifos) 1211 1.1 haad { 1212 1.1 haad /* Create fifos */ 1213 1.1 haad if (((mkfifo(fifos->client_path, 0600) == -1) && errno != EEXIST) || 1214 1.1 haad ((mkfifo(fifos->server_path, 0600) == -1) && errno != EEXIST)) { 1215 1.1 haad syslog(LOG_ERR, "%s: Failed to create a fifo.\n", __func__); 1216 1.1 haad stack; 1217 1.1 haad return -errno; 1218 1.1 haad } 1219 1.1 haad 1220 1.1 haad struct stat st; 1221 1.1 haad 1222 1.1 haad /* Warn about wrong permissions if applicable */ 1223 1.1 haad if ((!stat(fifos->client_path, &st)) && (st.st_mode & 0777) != 0600) 1224 1.1 haad syslog(LOG_WARNING, "Fixing wrong permissions on %s", 1225 1.1 haad fifos->client_path); 1226 1.1 haad 1227 1.1 haad if ((!stat(fifos->server_path, &st)) && (st.st_mode & 0777) != 0600) 1228 1.1 haad syslog(LOG_WARNING, "Fixing wrong permissions on %s", 1229 1.1 haad fifos->server_path); 1230 1.1 haad 1231 1.1 haad /* If they were already there, make sure permissions are ok. */ 1232 1.1 haad if (chmod(fifos->client_path, 0600)) { 1233 1.1 haad syslog(LOG_ERR, "Unable to set correct file permissions on %s", 1234 1.1 haad fifos->client_path); 1235 1.1 haad return -errno; 1236 1.1 haad } 1237 1.1 haad 1238 1.1 haad if (chmod(fifos->server_path, 0600)) { 1239 1.1 haad syslog(LOG_ERR, "Unable to set correct file permissions on %s", 1240 1.1 haad fifos->server_path); 1241 1.1 haad return -errno; 1242 1.1 haad } 1243 1.1 haad 1244 1.1 haad /* Need to open read+write or we will block or fail */ 1245 1.1 haad if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) { 1246 1.1 haad stack; 1247 1.1 haad return -errno; 1248 1.1 haad } 1249 1.1 haad 1250 1.1 haad /* Need to open read+write for select() to work. */ 1251 1.1 haad if ((fifos->client = open(fifos->client_path, O_RDWR)) < 0) { 1252 1.1 haad stack; 1253 1.1 haad close(fifos->server); 1254 1.1 haad return -errno; 1255 1.1 haad } 1256 1.1 haad 1257 1.1 haad return 0; 1258 1.1 haad } 1259 1.1 haad 1260 1.1 haad /* 1261 1.1 haad * Read message from client making sure that data is available 1262 1.1 haad * and a complete message is read. Must not block indefinitely. 1263 1.1 haad */ 1264 1.1 haad static int _client_read(struct dm_event_fifos *fifos, 1265 1.1 haad struct dm_event_daemon_message *msg) 1266 1.1 haad { 1267 1.1 haad struct timeval t; 1268 1.1 haad unsigned bytes = 0; 1269 1.1 haad int ret = 0; 1270 1.1 haad fd_set fds; 1271 1.1 haad int header = 1; 1272 1.1 haad size_t size = 2 * sizeof(uint32_t); /* status + size */ 1273 1.1 haad char *buf = alloca(size); 1274 1.1 haad 1275 1.1 haad msg->data = NULL; 1276 1.1 haad 1277 1.1 haad errno = 0; 1278 1.1 haad while (bytes < size && errno != EOF) { 1279 1.1 haad /* Watch client read FIFO for input. */ 1280 1.1 haad FD_ZERO(&fds); 1281 1.1 haad FD_SET(fifos->client, &fds); 1282 1.1 haad t.tv_sec = 1; 1283 1.1 haad t.tv_usec = 0; 1284 1.1 haad ret = select(fifos->client + 1, &fds, NULL, NULL, &t); 1285 1.1 haad 1286 1.1 haad if (!ret && !bytes) /* nothing to read */ 1287 1.1 haad return 0; 1288 1.1 haad 1289 1.1 haad if (!ret) /* trying to finish read */ 1290 1.1 haad continue; 1291 1.1 haad 1292 1.1 haad if (ret < 0) /* error */ 1293 1.1 haad return 0; 1294 1.1 haad 1295 1.1 haad ret = read(fifos->client, buf + bytes, size - bytes); 1296 1.1 haad bytes += ret > 0 ? ret : 0; 1297 1.1 haad if (bytes == 2 * sizeof(uint32_t) && header) { 1298 1.1 haad msg->cmd = ntohl(*((uint32_t *) buf)); 1299 1.1 haad msg->size = ntohl(*((uint32_t *) buf + 1)); 1300 1.1 haad buf = msg->data = dm_malloc(msg->size); 1301 1.1 haad size = msg->size; 1302 1.1 haad bytes = 0; 1303 1.1 haad header = 0; 1304 1.1 haad } 1305 1.1 haad } 1306 1.1 haad 1307 1.1 haad if (bytes != size) { 1308 1.1 haad if (msg->data) 1309 1.1 haad dm_free(msg->data); 1310 1.1 haad msg->data = NULL; 1311 1.1 haad msg->size = 0; 1312 1.1 haad } 1313 1.1 haad 1314 1.1 haad return bytes == size; 1315 1.1 haad } 1316 1.1 haad 1317 1.1 haad /* 1318 1.1 haad * Write a message to the client making sure that it is ready to write. 1319 1.1 haad */ 1320 1.1 haad static int _client_write(struct dm_event_fifos *fifos, 1321 1.1 haad struct dm_event_daemon_message *msg) 1322 1.1 haad { 1323 1.1 haad unsigned bytes = 0; 1324 1.1 haad int ret = 0; 1325 1.1 haad fd_set fds; 1326 1.1 haad 1327 1.1 haad size_t size = 2 * sizeof(uint32_t) + msg->size; 1328 1.1 haad char *buf = alloca(size); 1329 1.1 haad 1330 1.1 haad *((uint32_t *)buf) = htonl(msg->cmd); 1331 1.1 haad *((uint32_t *)buf + 1) = htonl(msg->size); 1332 1.1 haad if (msg->data) 1333 1.1 haad memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size); 1334 1.1 haad 1335 1.1 haad errno = 0; 1336 1.1 haad while (bytes < size && errno != EIO) { 1337 1.1 haad do { 1338 1.1 haad /* Watch client write FIFO to be ready for output. */ 1339 1.1 haad FD_ZERO(&fds); 1340 1.1 haad FD_SET(fifos->server, &fds); 1341 1.1 haad } while (select(fifos->server + 1, NULL, &fds, NULL, NULL) != 1342 1.1 haad 1); 1343 1.1 haad 1344 1.1 haad ret = write(fifos->server, buf + bytes, size - bytes); 1345 1.1 haad bytes += ret > 0 ? ret : 0; 1346 1.1 haad } 1347 1.1 haad 1348 1.1 haad return bytes == size; 1349 1.1 haad } 1350 1.1 haad 1351 1.1 haad /* 1352 1.1 haad * Handle a client request. 1353 1.1 haad * 1354 1.1 haad * We put the request handling functions into 1355 1.1 haad * a list because of the growing number. 1356 1.1 haad */ 1357 1.1 haad static int _handle_request(struct dm_event_daemon_message *msg, 1358 1.1 haad struct message_data *message_data) 1359 1.1 haad { 1360 1.1 haad static struct { 1361 1.1 haad unsigned int cmd; 1362 1.1 haad int (*f)(struct message_data *); 1363 1.1 haad } requests[] = { 1364 1.1 haad { DM_EVENT_CMD_REGISTER_FOR_EVENT, _register_for_event}, 1365 1.1 haad { DM_EVENT_CMD_UNREGISTER_FOR_EVENT, _unregister_for_event}, 1366 1.1 haad { DM_EVENT_CMD_GET_REGISTERED_DEVICE, _get_registered_device}, 1367 1.1 haad { DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE, 1368 1.1 haad _get_next_registered_device}, 1369 1.1 haad { DM_EVENT_CMD_SET_TIMEOUT, _set_timeout}, 1370 1.1 haad { DM_EVENT_CMD_GET_TIMEOUT, _get_timeout}, 1371 1.1 haad { DM_EVENT_CMD_ACTIVE, _active}, 1372 1.1 haad }, *req; 1373 1.1 haad 1374 1.1 haad for (req = requests; req < requests + sizeof(requests); req++) 1375 1.1 haad if (req->cmd == msg->cmd) 1376 1.1 haad return req->f(message_data); 1377 1.1 haad 1378 1.1 haad return -EINVAL; 1379 1.1 haad } 1380 1.1 haad 1381 1.1 haad /* Process a request passed from the communication thread. */ 1382 1.1 haad static int _do_process_request(struct dm_event_daemon_message *msg) 1383 1.1 haad { 1384 1.1 haad int ret; 1385 1.1 haad char *answer; 1386 1.1 haad static struct message_data message_data; 1387 1.1 haad 1388 1.1 haad /* Parse the message. */ 1389 1.1 haad memset(&message_data, 0, sizeof(message_data)); 1390 1.1 haad message_data.msg = msg; 1391 1.1 haad if (msg->cmd == DM_EVENT_CMD_HELLO) { 1392 1.1 haad ret = 0; 1393 1.1 haad answer = msg->data; 1394 1.1 haad if (answer) { 1395 1.1 haad msg->size = dm_asprintf(&(msg->data), "%s HELLO", answer); 1396 1.1 haad dm_free(answer); 1397 1.1 haad } else { 1398 1.1 haad msg->size = 0; 1399 1.1 haad msg->data = NULL; 1400 1.1 haad } 1401 1.1 haad } else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) { 1402 1.1 haad stack; 1403 1.1 haad ret = -EINVAL; 1404 1.1 haad } else 1405 1.1 haad ret = _handle_request(msg, &message_data); 1406 1.1 haad 1407 1.1 haad msg->cmd = ret; 1408 1.1 haad if (!msg->data) 1409 1.1 haad msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret)); 1410 1.1 haad 1411 1.1 haad _free_message(&message_data); 1412 1.1 haad 1413 1.1 haad return ret; 1414 1.1 haad } 1415 1.1 haad 1416 1.1 haad /* Only one caller at a time. */ 1417 1.1 haad static void _process_request(struct dm_event_fifos *fifos) 1418 1.1 haad { 1419 1.1 haad struct dm_event_daemon_message msg; 1420 1.1 haad 1421 1.1 haad memset(&msg, 0, sizeof(msg)); 1422 1.1 haad 1423 1.1 haad /* 1424 1.1 haad * Read the request from the client (client_read, client_write 1425 1.1 haad * give true on success and false on failure). 1426 1.1 haad */ 1427 1.1 haad if (!_client_read(fifos, &msg)) 1428 1.1 haad return; 1429 1.1 haad 1430 1.1 haad /* _do_process_request fills in msg (if memory allows for 1431 1.1 haad data, otherwise just cmd and size = 0) */ 1432 1.1 haad _do_process_request(&msg); 1433 1.1 haad 1434 1.1 haad if (!_client_write(fifos, &msg)) 1435 1.1 haad stack; 1436 1.1 haad 1437 1.1 haad if (msg.data) 1438 1.1 haad dm_free(msg.data); 1439 1.1 haad } 1440 1.1 haad 1441 1.1 haad static void _cleanup_unused_threads(void) 1442 1.1 haad { 1443 1.1 haad int ret; 1444 1.1 haad struct dm_list *l; 1445 1.1 haad struct thread_status *thread; 1446 1.1 haad 1447 1.1 haad _lock_mutex(); 1448 1.1 haad while ((l = dm_list_first(&_thread_registry_unused))) { 1449 1.1 haad thread = dm_list_item(l, struct thread_status); 1450 1.1 haad if (thread->processing) 1451 1.1 haad break; /* cleanup on the next round */ 1452 1.1 haad 1453 1.1 haad if (thread->status == DM_THREAD_RUNNING) { 1454 1.1 haad thread->status = DM_THREAD_SHUTDOWN; 1455 1.1 haad break; 1456 1.1 haad } 1457 1.1 haad 1458 1.1 haad if (thread->status == DM_THREAD_SHUTDOWN) { 1459 1.1 haad if (!thread->events) { 1460 1.1 haad /* turn codes negative -- should we be returning this? */ 1461 1.1 haad ret = _terminate_thread(thread); 1462 1.1 haad 1463 1.1 haad if (ret == ESRCH) { 1464 1.1 haad thread->status = DM_THREAD_DONE; 1465 1.1 haad } else if (ret) { 1466 1.1 haad syslog(LOG_ERR, 1467 1.1 haad "Unable to terminate thread: %s\n", 1468 1.1 haad strerror(-ret)); 1469 1.1 haad stack; 1470 1.1 haad } 1471 1.1 haad break; 1472 1.1 haad } 1473 1.1 haad 1474 1.1 haad dm_list_del(l); 1475 1.1 haad syslog(LOG_ERR, 1476 1.1 haad "thread can't be on unused list unless !thread->events"); 1477 1.1 haad thread->status = DM_THREAD_RUNNING; 1478 1.1 haad LINK_THREAD(thread); 1479 1.1 haad 1480 1.1 haad continue; 1481 1.1 haad } 1482 1.1 haad 1483 1.1 haad if (thread->status == DM_THREAD_DONE) { 1484 1.1 haad dm_list_del(l); 1485 1.1 haad pthread_join(thread->thread, NULL); 1486 1.1 haad _lib_put(thread->dso_data); 1487 1.1 haad _free_thread_status(thread); 1488 1.1 haad } 1489 1.1 haad } 1490 1.1 haad 1491 1.1 haad _unlock_mutex(); 1492 1.1 haad } 1493 1.1 haad 1494 1.1 haad static void _sig_alarm(int signum __attribute((unused))) 1495 1.1 haad { 1496 1.1 haad pthread_testcancel(); 1497 1.1 haad } 1498 1.1 haad 1499 1.1 haad /* Init thread signal handling. */ 1500 1.1 haad static void _init_thread_signals(void) 1501 1.1 haad { 1502 1.1 haad sigset_t my_sigset; 1503 1.1 haad struct sigaction act; 1504 1.1 haad 1505 1.1 haad memset(&act, 0, sizeof(act)); 1506 1.1 haad act.sa_handler = _sig_alarm; 1507 1.1 haad sigaction(SIGALRM, &act, NULL); 1508 1.1 haad sigfillset(&my_sigset); 1509 1.1 haad 1510 1.1 haad /* These are used for exiting */ 1511 1.1 haad sigdelset(&my_sigset, SIGTERM); 1512 1.1 haad sigdelset(&my_sigset, SIGINT); 1513 1.1 haad sigdelset(&my_sigset, SIGHUP); 1514 1.1 haad sigdelset(&my_sigset, SIGQUIT); 1515 1.1 haad 1516 1.1 haad pthread_sigmask(SIG_BLOCK, &my_sigset, NULL); 1517 1.1 haad } 1518 1.1 haad 1519 1.1 haad /* 1520 1.1 haad * exit_handler 1521 1.1 haad * @sig 1522 1.1 haad * 1523 1.1 haad * Set the global variable which the process should 1524 1.1 haad * be watching to determine when to exit. 1525 1.1 haad */ 1526 1.1 haad static void _exit_handler(int sig __attribute((unused))) 1527 1.1 haad { 1528 1.1 haad /* 1529 1.1 haad * We exit when '_exit_now' is set. 1530 1.1 haad * That is, when a signal has been received. 1531 1.1 haad * 1532 1.1 haad * We can not simply set '_exit_now' unless all 1533 1.1 haad * threads are done processing. 1534 1.1 haad */ 1535 1.1 haad if (!_thread_registries_empty) { 1536 1.1 haad syslog(LOG_ERR, "There are still devices being monitored."); 1537 1.1 haad syslog(LOG_ERR, "Refusing to exit."); 1538 1.1 haad } else 1539 1.1 haad _exit_now = 1; 1540 1.1 haad 1541 1.1 haad } 1542 1.1 haad 1543 1.1 haad static int _lock_pidfile(void) 1544 1.1 haad { 1545 1.1 haad int lf; 1546 1.1 haad char pidfile[] = DMEVENTD_PIDFILE; 1547 1.1 haad 1548 1.1 haad if ((lf = open(pidfile, O_CREAT | O_RDWR, 0644)) < 0) 1549 1.1 haad exit(EXIT_OPEN_PID_FAILURE); 1550 1.1 haad 1551 1.1 haad if (flock(lf, LOCK_EX | LOCK_NB) < 0) 1552 1.1 haad exit(EXIT_LOCKFILE_INUSE); 1553 1.1 haad 1554 1.1 haad if (!_storepid(lf)) 1555 1.1 haad exit(EXIT_FAILURE); 1556 1.1 haad 1557 1.1 haad return 0; 1558 1.1 haad } 1559 1.1 haad 1560 1.1 haad #ifdef linux 1561 1.1 haad /* 1562 1.1 haad * Protection against OOM killer if kernel supports it 1563 1.1 haad */ 1564 1.1 haad static int _set_oom_adj(int val) 1565 1.1 haad { 1566 1.1 haad FILE *fp; 1567 1.1 haad 1568 1.1 haad struct stat st; 1569 1.1 haad 1570 1.1 haad if (stat(OOM_ADJ_FILE, &st) == -1) { 1571 1.1 haad if (errno == ENOENT) 1572 1.1 haad DEBUGLOG(OOM_ADJ_FILE " not found"); 1573 1.1 haad else 1574 1.1 haad perror(OOM_ADJ_FILE ": stat failed"); 1575 1.1 haad return 1; 1576 1.1 haad } 1577 1.1 haad 1578 1.1 haad if (!(fp = fopen(OOM_ADJ_FILE, "w"))) { 1579 1.1 haad perror(OOM_ADJ_FILE ": fopen failed"); 1580 1.1 haad return 0; 1581 1.1 haad } 1582 1.1 haad 1583 1.1 haad fprintf(fp, "%i", val); 1584 1.1 haad if (dm_fclose(fp)) 1585 1.1 haad perror(OOM_ADJ_FILE ": fclose failed"); 1586 1.1 haad 1587 1.1 haad return 1; 1588 1.1 haad } 1589 1.1 haad #endif 1590 1.1 haad 1591 1.1 haad static void _daemonize(void) 1592 1.1 haad { 1593 1.1 haad int child_status; 1594 1.1 haad int fd; 1595 1.1 haad pid_t pid; 1596 1.1 haad struct rlimit rlim; 1597 1.1 haad struct timeval tval; 1598 1.1 haad sigset_t my_sigset; 1599 1.1 haad 1600 1.1 haad sigemptyset(&my_sigset); 1601 1.1 haad if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) { 1602 1.1 haad fprintf(stderr, "Unable to restore signals.\n"); 1603 1.1 haad exit(EXIT_FAILURE); 1604 1.1 haad } 1605 1.1 haad signal(SIGTERM, &_exit_handler); 1606 1.1 haad 1607 1.1 haad switch (pid = fork()) { 1608 1.1 haad case -1: 1609 1.1 haad perror("fork failed:"); 1610 1.1 haad exit(EXIT_FAILURE); 1611 1.1 haad 1612 1.1 haad case 0: /* Child */ 1613 1.1 haad break; 1614 1.1 haad 1615 1.1 haad default: 1616 1.1 haad /* Wait for response from child */ 1617 1.1 haad while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) { 1618 1.1 haad tval.tv_sec = 0; 1619 1.1 haad tval.tv_usec = 250000; /* .25 sec */ 1620 1.1 haad select(0, NULL, NULL, NULL, &tval); 1621 1.1 haad } 1622 1.1 haad 1623 1.1 haad if (_exit_now) /* Child has signaled it is ok - we can exit now */ 1624 1.1 haad exit(EXIT_SUCCESS); 1625 1.1 haad 1626 1.1 haad /* Problem with child. Determine what it is by exit code */ 1627 1.1 haad switch (WEXITSTATUS(child_status)) { 1628 1.1 haad case EXIT_LOCKFILE_INUSE: 1629 1.1 haad fprintf(stderr, "Another dmeventd daemon is already running\n"); 1630 1.1 haad break; 1631 1.1 haad case EXIT_DESC_CLOSE_FAILURE: 1632 1.1 haad case EXIT_DESC_OPEN_FAILURE: 1633 1.1 haad case EXIT_OPEN_PID_FAILURE: 1634 1.1 haad case EXIT_FIFO_FAILURE: 1635 1.1 haad case EXIT_CHDIR_FAILURE: 1636 1.1 haad default: 1637 1.1 haad fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status)); 1638 1.1 haad break; 1639 1.1 haad } 1640 1.1 haad 1641 1.1 haad exit(WEXITSTATUS(child_status)); 1642 1.1 haad } 1643 1.1 haad 1644 1.1 haad if (chdir("/")) 1645 1.1 haad exit(EXIT_CHDIR_FAILURE); 1646 1.1 haad 1647 1.1 haad if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) 1648 1.1 haad fd = 256; /* just have to guess */ 1649 1.1 haad else 1650 1.1 haad fd = rlim.rlim_cur; 1651 1.1 haad 1652 1.1 haad for (--fd; fd >= 0; fd--) 1653 1.1 haad close(fd); 1654 1.1 haad 1655 1.1 haad if ((open("/dev/null", O_RDONLY) < 0) || 1656 1.1 haad (open("/dev/null", O_WRONLY) < 0) || 1657 1.1 haad (open("/dev/null", O_WRONLY) < 0)) 1658 1.1 haad exit(EXIT_DESC_OPEN_FAILURE); 1659 1.1 haad 1660 1.1 haad setsid(); 1661 1.1 haad } 1662 1.1 haad 1663 1.1 haad static void usage(char *prog, FILE *file) 1664 1.1 haad { 1665 1.1 haad fprintf(file, "Usage:\n"); 1666 1.1 haad fprintf(file, "%s [Vhd]\n", prog); 1667 1.1 haad fprintf(file, "\n"); 1668 1.1 haad fprintf(file, " -V Show version of dmeventd\n"); 1669 1.1 haad fprintf(file, " -h Show this help information\n"); 1670 1.1 haad fprintf(file, " -d Don't fork, run in the foreground\n"); 1671 1.1 haad fprintf(file, "\n"); 1672 1.1 haad } 1673 1.1 haad 1674 1.1 haad int main(int argc, char *argv[]) 1675 1.1 haad { 1676 1.1 haad int ret; 1677 1.1 haad signed char opt; 1678 1.1 haad struct dm_event_fifos fifos; 1679 1.1 haad //struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON}; 1680 1.1 haad 1681 1.1 haad opterr = 0; 1682 1.1 haad optind = 0; 1683 1.1 haad 1684 1.1 haad while ((opt = getopt(argc, argv, "?hVd")) != EOF) { 1685 1.1 haad switch (opt) { 1686 1.1 haad case 'h': 1687 1.1 haad usage(argv[0], stdout); 1688 1.1 haad exit(0); 1689 1.1 haad case '?': 1690 1.1 haad usage(argv[0], stderr); 1691 1.1 haad exit(0); 1692 1.1 haad case 'd': 1693 1.1 haad _debug++; 1694 1.1 haad break; 1695 1.1 haad case 'V': 1696 1.1 haad printf("dmeventd version: %s\n", DM_LIB_VERSION); 1697 1.1 haad exit(1); 1698 1.1 haad break; 1699 1.1 haad } 1700 1.1 haad } 1701 1.1 haad 1702 1.1 haad if (!_debug) 1703 1.1 haad _daemonize(); 1704 1.1 haad 1705 1.1 haad openlog("dmeventd", LOG_PID, LOG_DAEMON); 1706 1.1 haad 1707 1.1 haad _lock_pidfile(); /* exits if failure */ 1708 1.1 haad 1709 1.1 haad /* Set the rest of the signals to cause '_exit_now' to be set */ 1710 1.1 haad signal(SIGINT, &_exit_handler); 1711 1.1 haad signal(SIGHUP, &_exit_handler); 1712 1.1 haad signal(SIGQUIT, &_exit_handler); 1713 1.1 haad 1714 1.1 haad #ifdef linux 1715 1.1 haad if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN)) 1716 1.1 haad syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer"); 1717 1.1 haad #endif 1718 1.1 haad 1719 1.1 haad _init_thread_signals(); 1720 1.1 haad 1721 1.1 haad //multilog_clear_logging(); 1722 1.1 haad //multilog_add_type(std_syslog, &logdata); 1723 1.1 haad //multilog_init_verbose(std_syslog, _LOG_DEBUG); 1724 1.1 haad //multilog_async(1); 1725 1.1 haad 1726 1.1 haad _init_fifos(&fifos); 1727 1.1 haad 1728 1.1 haad pthread_mutex_init(&_global_mutex, NULL); 1729 1.1 haad 1730 1.1 haad #ifdef MCL_CURRENT 1731 1.1 haad if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) 1732 1.1 haad exit(EXIT_FAILURE); 1733 1.1 haad #endif 1734 1.1 haad 1735 1.1 haad if ((ret = _open_fifos(&fifos))) 1736 1.1 haad exit(EXIT_FIFO_FAILURE); 1737 1.1 haad 1738 1.1 haad /* Signal parent, letting them know we are ready to go. */ 1739 1.1 haad kill(getppid(), SIGTERM); 1740 1.1 haad syslog(LOG_NOTICE, "dmeventd ready for processing."); 1741 1.1 haad 1742 1.1 haad while (!_exit_now) { 1743 1.1 haad _process_request(&fifos); 1744 1.1 haad _cleanup_unused_threads(); 1745 1.1 haad if (!dm_list_empty(&_thread_registry) 1746 1.1 haad || !dm_list_empty(&_thread_registry_unused)) 1747 1.1 haad _thread_registries_empty = 0; 1748 1.1 haad else 1749 1.1 haad _thread_registries_empty = 1; 1750 1.1 haad } 1751 1.1 haad 1752 1.1 haad _exit_dm_lib(); 1753 1.1 haad 1754 1.1 haad #ifdef MCL_CURRENT 1755 1.1 haad munlockall(); 1756 1.1 haad #endif 1757 1.1 haad pthread_mutex_destroy(&_global_mutex); 1758 1.1 haad 1759 1.1 haad syslog(LOG_NOTICE, "dmeventd shutting down."); 1760 1.1 haad closelog(); 1761 1.1 haad 1762 1.1 haad exit(EXIT_SUCCESS); 1763 1.1 haad } 1764