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