1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * syseventd - The system event daemon 29 * 30 * This daemon dispatches event buffers received from the 31 * kernel to all interested SLM clients. SLMs in turn 32 * deliver the buffers to their particular application 33 * clients. 34 */ 35 #include <stdio.h> 36 #include <sys/types.h> 37 #include <dirent.h> 38 #include <stdarg.h> 39 #include <stddef.h> 40 #include <stdlib.h> 41 #include <dlfcn.h> 42 #include <door.h> 43 #include <errno.h> 44 #include <fcntl.h> 45 #include <signal.h> 46 #include <strings.h> 47 #include <unistd.h> 48 #include <synch.h> 49 #include <syslog.h> 50 #include <thread.h> 51 #include <libsysevent.h> 52 #include <limits.h> 53 #include <locale.h> 54 #include <sys/sysevent.h> 55 #include <sys/sysevent_impl.h> 56 #include <sys/modctl.h> 57 #include <sys/stat.h> 58 #include <sys/systeminfo.h> 59 #include <sys/wait.h> 60 61 #include "sysevent_signal.h" 62 #include "syseventd.h" 63 #include "message.h" 64 65 extern int insert_client(void *client, int client_type, int retry_limit); 66 extern void delete_client(int id); 67 extern void initialize_client_tbl(void); 68 69 extern struct sysevent_client *sysevent_client_tbl[]; 70 extern mutex_t client_tbl_lock; 71 72 #define DEBUG_LEVEL_FORK 9 /* will run in background at all */ 73 /* levels less than DEBUG_LEVEL_FORK */ 74 75 int debug_level = 0; 76 char *root_dir = ""; /* Relative root for lock and door */ 77 78 /* Maximum number of outstanding events dispatched */ 79 #define SE_EVENT_DISPATCH_CNT 100 80 81 static int upcall_door; /* Kernel event door */ 82 static int door_upcall_retval; /* Kernel event posting return value */ 83 static int fini_pending = 0; /* fini pending flag */ 84 static int deliver_buf = 0; /* Current event buffer from kernel */ 85 static int dispatch_buf = 0; /* Current event buffer dispatched */ 86 static sysevent_t **eventbuf; /* Global array of event buffers */ 87 static struct ev_completion *event_compq; /* Event completion queue */ 88 static mutex_t ev_comp_lock; /* Event completion queue lock */ 89 static mutex_t err_mutex; /* error logging lock */ 90 static mutex_t door_lock; /* sync door return access */ 91 static rwlock_t mod_unload_lock; /* sync module unloading */ 92 93 /* declarations and definitions for avoiding multiple daemons running */ 94 #define DAEMON_LOCK_FILE "/var/run/syseventd.lock" 95 char local_lock_file[PATH_MAX + 1]; 96 static int hold_daemon_lock; 97 static int daemon_lock_fd; 98 99 /* 100 * sema_eventbuf - guards against the global buffer eventbuf 101 * being written to before it has been dispatched to clients 102 * 103 * sema_dispatch - synchronizes between the kernel uploading thread 104 * (producer) and the userland dispatch_message thread (consumer). 105 * 106 * sema_resource - throttles outstanding event consumption. 107 * 108 * event_comp_cv - synchronizes threads waiting for the event completion queue 109 * to empty or become active. 110 */ 111 static sema_t sema_eventbuf, sema_dispatch, sema_resource; 112 static cond_t event_comp_cv; 113 114 /* Self-tuning concurrency level */ 115 #define MIN_CONCURRENCY_LEVEL 4 116 static int concurrency_level = MIN_CONCURRENCY_LEVEL; 117 118 119 /* SLM defines */ 120 #define MODULE_SUFFIX ".so" 121 #define EVENT_FINI "slm_fini" 122 #define EVENT_INIT "slm_init" 123 124 #define SE_TIMEOUT 60 /* Client dispatch timeout (seconds) */ 125 126 /* syslog message related */ 127 static int logflag = 0; 128 static char *prog; 129 130 /* function prototypes */ 131 static void door_upcall(void *cookie, char *args, size_t alen, door_desc_t *ddp, 132 uint_t ndid); 133 static void dispatch_message(void); 134 static int dispatch(void); 135 static void event_completion_thr(void); 136 static void usage(void); 137 138 static void syseventd_init(void); 139 static void syseventd_fini(int sig); 140 141 static pid_t enter_daemon_lock(void); 142 static void exit_daemon_lock(void); 143 144 static void 145 usage() { 146 (void) fprintf(stderr, "usage: syseventd [-d <debug_level>] " 147 "[-r <root_dir>]\n"); 148 (void) fprintf(stderr, "higher debug levels get progressively "); 149 (void) fprintf(stderr, "more detailed debug information.\n"); 150 (void) fprintf(stderr, "syseventd will run in background if "); 151 (void) fprintf(stderr, "run with a debug_level less than %d.\n", 152 DEBUG_LEVEL_FORK); 153 exit(2); 154 } 155 156 157 /* common exit function which ensures releasing locks */ 158 void 159 syseventd_exit(int status) 160 { 161 syseventd_print(1, "exit status = %d\n", status); 162 163 if (hold_daemon_lock) { 164 exit_daemon_lock(); 165 } 166 167 exit(status); 168 } 169 170 171 /* 172 * hup_handler - SIGHUP handler. SIGHUP is used to force a reload of 173 * all SLMs. During fini, events are drained from all 174 * client event queues. The events that have been consumed 175 * by all clients are freed from the kernel event queue. 176 * 177 * Events that have not yet been delivered to all clients 178 * are not freed and will be replayed after all SLMs have 179 * been (re)loaded. 180 * 181 * After all client event queues have been drained, each 182 * SLM client is unloaded. The init phase will (re)load 183 * each SLM and initiate event replay and delivery from 184 * the kernel. 185 * 186 */ 187 /*ARGSUSED*/ 188 static void 189 hup_handler(int sig) 190 { 191 syseventd_err_print(SIGHUP_CAUGHT); 192 (void) fflush(0); 193 syseventd_fini(sig); 194 syseventd_init(); 195 syseventd_err_print(DAEMON_RESTARTED); 196 (void) fflush(0); 197 } 198 199 /* 200 * Fault handler for other signals caught 201 */ 202 /*ARGSUSED*/ 203 static void 204 flt_handler(int sig) 205 { 206 char signame[SIG2STR_MAX]; 207 208 if (sig2str(sig, signame) == -1) { 209 syseventd_err_print(UNKNOWN_SIGNAL_CAUGHT, sig); 210 } 211 212 (void) se_signal_sethandler(sig, SIG_DFL, NULL); 213 214 switch (sig) { 215 case SIGINT: 216 case SIGSTOP: 217 case SIGTERM: 218 /* Close kernel door */ 219 (void) door_revoke(upcall_door); 220 221 /* Gracefully exit current event delivery threads */ 222 syseventd_fini(sig); 223 224 (void) fflush(0); 225 (void) se_signal_unblockall(); 226 syseventd_exit(1); 227 /*NOTREACHED*/ 228 case SIGCLD: 229 /* No need to abort on a SIGCLD */ 230 break; 231 default: 232 syseventd_err_print(FATAL_ERROR); 233 abort(); 234 235 } 236 } 237 238 /* 239 * Daemon parent process only. 240 * Child process signal to indicate successful daemon initialization. 241 * This is the normal and expected exit path of the daemon parent. 242 */ 243 /*ARGSUSED*/ 244 static void 245 sigusr1(int sig) 246 { 247 syseventd_exit(0); 248 } 249 250 static void 251 sigwait_thr() 252 { 253 int sig; 254 int err; 255 sigset_t signal_set; 256 257 for (;;) { 258 syseventd_print(3, "sigwait thread waiting for signal\n"); 259 (void) sigfillset(&signal_set); 260 err = sigwait(&signal_set, &sig); 261 if (err) { 262 syseventd_exit(2); 263 } 264 265 /* 266 * Block all signals until the signal handler completes 267 */ 268 if (sig == SIGHUP) { 269 hup_handler(sig); 270 } else { 271 flt_handler(sig); 272 } 273 } 274 /* NOTREACHED */ 275 } 276 277 static void 278 set_root_dir(char *dir) 279 { 280 root_dir = malloc(strlen(dir) + 1); 281 if (root_dir == NULL) { 282 syseventd_err_print(INIT_ROOT_DIR_ERR, strerror(errno)); 283 syseventd_exit(2); 284 } 285 (void) strcpy(root_dir, dir); 286 } 287 288 int 289 main(int argc, char **argv) 290 { 291 int i, c; 292 int fd; 293 pid_t pid; 294 int has_forked = 0; 295 extern char *optarg; 296 297 (void) setlocale(LC_ALL, ""); 298 (void) textdomain(TEXT_DOMAIN); 299 300 if (getuid() != 0) { 301 (void) fprintf(stderr, "Must be root to run syseventd\n"); 302 syseventd_exit(1); 303 } 304 305 if (argc > 5) { 306 usage(); 307 } 308 309 if ((prog = strrchr(argv[0], '/')) == NULL) { 310 prog = argv[0]; 311 } else { 312 prog++; 313 } 314 315 while ((c = getopt(argc, argv, "d:r:")) != EOF) { 316 switch (c) { 317 case 'd': 318 debug_level = atoi(optarg); 319 break; 320 case 'r': 321 /* 322 * Private flag for suninstall to run 323 * daemon during install. 324 */ 325 set_root_dir(optarg); 326 break; 327 case '?': 328 default: 329 usage(); 330 } 331 } 332 333 /* demonize ourselves */ 334 if (debug_level < DEBUG_LEVEL_FORK) { 335 336 sigset_t mask; 337 338 (void) sigset(SIGUSR1, sigusr1); 339 340 (void) sigemptyset(&mask); 341 (void) sigaddset(&mask, SIGUSR1); 342 (void) sigprocmask(SIG_BLOCK, &mask, NULL); 343 344 if ((pid = fork()) == (pid_t)-1) { 345 (void) fprintf(stderr, 346 "syseventd: fork failed - %s\n", strerror(errno)); 347 syseventd_exit(1); 348 } 349 350 if (pid != 0) { 351 /* 352 * parent 353 * handshake with the daemon so that dependents 354 * of the syseventd service don't start up until 355 * the service is actually functional 356 */ 357 int status; 358 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL); 359 360 if (waitpid(pid, &status, 0) != pid) { 361 /* 362 * child process signal indicating 363 * successful daemon initialization 364 */ 365 syseventd_exit(0); 366 } 367 /* child exited implying unsuccessful startup */ 368 syseventd_exit(1); 369 } 370 371 /* child */ 372 373 has_forked = 1; 374 (void) sigset(SIGUSR1, SIG_DFL); 375 (void) sigprocmask(SIG_UNBLOCK, &mask, NULL); 376 377 (void) chdir("/"); 378 (void) setsid(); 379 if (debug_level <= 1) { 380 closefrom(0); 381 fd = open("/dev/null", 0); 382 (void) dup2(fd, 1); 383 (void) dup2(fd, 2); 384 logflag = 1; 385 } 386 } 387 388 openlog("syseventd", LOG_PID, LOG_DAEMON); 389 390 (void) mutex_init(&err_mutex, USYNC_THREAD, NULL); 391 392 syseventd_print(8, 393 "syseventd started, debug level = %d\n", debug_level); 394 395 /* only one instance of syseventd can run at a time */ 396 if ((pid = enter_daemon_lock()) != getpid()) { 397 syseventd_print(1, 398 "event daemon pid %ld already running\n", pid); 399 exit(3); 400 } 401 402 /* initialize semaphores and eventbuf */ 403 (void) sema_init(&sema_eventbuf, SE_EVENT_DISPATCH_CNT, 404 USYNC_THREAD, NULL); 405 (void) sema_init(&sema_dispatch, 0, USYNC_THREAD, NULL); 406 (void) sema_init(&sema_resource, SE_EVENT_DISPATCH_CNT, 407 USYNC_THREAD, NULL); 408 (void) cond_init(&event_comp_cv, USYNC_THREAD, NULL); 409 eventbuf = (sysevent_t **)calloc(SE_EVENT_DISPATCH_CNT, 410 sizeof (sysevent_t *)); 411 if (eventbuf == NULL) { 412 syseventd_print(1, "Unable to allocate event buffer array\n"); 413 exit(2); 414 } 415 for (i = 0; i < SE_EVENT_DISPATCH_CNT; ++i) { 416 eventbuf[i] = malloc(LOGEVENT_BUFSIZE); 417 if (eventbuf[i] == NULL) { 418 syseventd_print(1, "Unable to allocate event " 419 "buffers\n"); 420 exit(2); 421 } 422 } 423 424 (void) mutex_init(&client_tbl_lock, USYNC_THREAD, NULL); 425 (void) mutex_init(&ev_comp_lock, USYNC_THREAD, NULL); 426 (void) mutex_init(&door_lock, USYNC_THREAD, NULL); 427 (void) rwlock_init(&mod_unload_lock, USYNC_THREAD, NULL); 428 429 event_compq = NULL; 430 431 syseventd_print(8, "start the message thread running\n"); 432 433 /* 434 * Block all signals to all threads include the main thread. 435 * The sigwait_thr thread will process any signals and initiate 436 * a graceful recovery if possible. 437 */ 438 if (se_signal_blockall() < 0) { 439 syseventd_err_print(INIT_SIG_BLOCK_ERR); 440 syseventd_exit(2); 441 } 442 443 if (thr_create(NULL, NULL, (void *(*)(void *))dispatch_message, 444 (void *)0, 0, NULL) < 0) { 445 syseventd_err_print(INIT_THR_CREATE_ERR, strerror(errno)); 446 syseventd_exit(2); 447 } 448 if (thr_create(NULL, NULL, 449 (void *(*)(void *))event_completion_thr, NULL, 450 THR_BOUND, NULL) != 0) { 451 syseventd_err_print(INIT_THR_CREATE_ERR, strerror(errno)); 452 syseventd_exit(2); 453 } 454 /* Create signal catching thread */ 455 if (thr_create(NULL, NULL, (void *(*)(void *))sigwait_thr, 456 NULL, 0, NULL) < 0) { 457 syseventd_err_print(INIT_THR_CREATE_ERR, strerror(errno)); 458 syseventd_exit(2); 459 } 460 461 setbuf(stdout, (char *)NULL); 462 463 /* Initialize and load SLM clients */ 464 initialize_client_tbl(); 465 syseventd_init(); 466 467 /* signal parent to indicate successful daemon initialization */ 468 if (has_forked) { 469 if (kill(getppid(), SIGUSR1) != 0) { 470 syseventd_err_print( 471 "signal to the parent failed - %s\n", 472 strerror(errno)); 473 syseventd_exit(2); 474 } 475 } 476 477 syseventd_print(8, "Pausing\n"); 478 479 for (;;) { 480 (void) pause(); 481 } 482 /* NOTREACHED */ 483 return (0); 484 } 485 486 /* 487 * door_upcall - called from the kernel via kernel sysevent door 488 * to upload event(s). 489 * 490 * This routine should never block. If resources are 491 * not available to immediately accept the event buffer 492 * EAGAIN is returned to the kernel. 493 * 494 * Once resources are available, the kernel is notified 495 * via a modctl interface to resume event delivery to 496 * syseventd. 497 * 498 */ 499 /*ARGSUSED*/ 500 static void 501 door_upcall(void *cookie, char *args, size_t alen, 502 door_desc_t *ddp, uint_t ndid) 503 { 504 sysevent_t *ev; 505 int rval; 506 507 508 (void) mutex_lock(&door_lock); 509 if (args == NULL) { 510 rval = EINVAL; 511 } else if (sema_trywait(&sema_eventbuf)) { 512 ev = (sysevent_t *) 513 &((log_event_upcall_arg_t *)(void *)args)->buf; 514 syseventd_print(2, "door_upcall: busy event %llx " 515 "retry\n", sysevent_get_seq(ev)); 516 rval = door_upcall_retval = EAGAIN; 517 } else { 518 /* 519 * Copy received message to local buffer. 520 */ 521 size_t size; 522 ev = (sysevent_t *) 523 &((log_event_upcall_arg_t *)(void *)args)->buf; 524 525 syseventd_print(2, "door_upcall: event %llx in eventbuf %d\n", 526 sysevent_get_seq(ev), deliver_buf); 527 size = sysevent_get_size(ev) > LOGEVENT_BUFSIZE ? 528 LOGEVENT_BUFSIZE : sysevent_get_size(ev); 529 (void) bcopy(ev, eventbuf[deliver_buf], size); 530 deliver_buf = (deliver_buf + 1) % SE_EVENT_DISPATCH_CNT; 531 rval = 0; 532 (void) sema_post(&sema_dispatch); 533 } 534 535 (void) mutex_unlock(&door_lock); 536 537 /* 538 * Filling in return values for door_return 539 */ 540 (void) door_return((void *)&rval, sizeof (rval), NULL, 0); 541 (void) door_return(NULL, 0, NULL, 0); 542 } 543 544 /* 545 * dispatch_message - dispatch message thread 546 * This thread spins until an event buffer is delivered 547 * delivered from the kernel. 548 * 549 * It will wait to dispatch an event to any clients 550 * until adequate resources are available to process 551 * the event buffer. 552 */ 553 static void 554 dispatch_message(void) 555 { 556 int error; 557 558 for (;;) { 559 syseventd_print(3, "dispatch_message: thread started\n"); 560 /* 561 * Spin till a message comes 562 */ 563 while (sema_wait(&sema_dispatch) != 0) { 564 syseventd_print(1, 565 "dispatch_message: sema_wait failed\n"); 566 (void) sleep(1); 567 } 568 569 syseventd_print(3, "dispatch_message: sema_dispatch\n"); 570 571 /* 572 * Wait for available resources 573 */ 574 while (sema_wait(&sema_resource) != 0) { 575 syseventd_print(1, "dispatch_message: sema_wait " 576 "failed\n"); 577 (void) sleep(1); 578 } 579 580 syseventd_print(2, "dispatch_message: eventbuf %d\n", 581 dispatch_buf); 582 583 /* 584 * Client dispatch 585 */ 586 do { 587 error = dispatch(); 588 } while (error == EAGAIN); 589 590 syseventd_print(2, "eventbuf %d dispatched\n", dispatch_buf); 591 dispatch_buf = (dispatch_buf + 1) % SE_EVENT_DISPATCH_CNT; 592 593 /* 594 * kernel received a busy signal - 595 * kickstart the kernel delivery thread 596 * door_lock blocks the kernel so we hold it for the 597 * shortest time possible. 598 */ 599 (void) mutex_lock(&door_lock); 600 if (door_upcall_retval == EAGAIN && !fini_pending) { 601 syseventd_print(3, "dispatch_message: retrigger " 602 "door_upcall_retval = %d\n", 603 door_upcall_retval); 604 (void) modctl(MODEVENTS, (uintptr_t)MODEVENTS_FLUSH, 605 NULL, NULL, NULL, 0); 606 door_upcall_retval = 0; 607 } 608 (void) mutex_unlock(&door_lock); 609 } 610 /* NOTREACHED */ 611 } 612 613 /* 614 * drain_eventq - Called to drain all pending events from the client's 615 * event queue. 616 */ 617 static void 618 drain_eventq(struct sysevent_client *scp, int status) 619 { 620 struct event_dispatch_pkg *d_pkg; 621 struct event_dispatchq *eventq, *eventq_next; 622 623 syseventd_print(3, "Draining eventq for client %d\n", 624 scp->client_num); 625 626 eventq = scp->eventq; 627 while (eventq) { 628 /* 629 * Mark all dispatched events as completed, but indicate the 630 * error status 631 */ 632 d_pkg = eventq->d_pkg; 633 634 syseventd_print(4, "drain event 0X%llx for client %d\n", 635 sysevent_get_seq(d_pkg->ev), scp->client_num); 636 637 if (d_pkg->completion_state == SE_NOT_DISPATCHED) { 638 d_pkg->completion_status = status; 639 d_pkg->completion_state = SE_COMPLETE; 640 (void) sema_post(d_pkg->completion_sema); 641 } 642 643 eventq_next = eventq->next; 644 free(eventq); 645 eventq = eventq_next; 646 scp->eventq = eventq; 647 } 648 } 649 650 /* 651 * client_deliver_event_thr - Client delivery thread 652 * This thread will process any events on this 653 * client's eventq. 654 */ 655 static void 656 client_deliver_event_thr(void *arg) 657 { 658 int flag, error, i; 659 sysevent_t *ev; 660 hrtime_t now; 661 module_t *mod; 662 struct event_dispatchq *eventq; 663 struct sysevent_client *scp; 664 struct event_dispatch_pkg *d_pkg; 665 666 scp = (struct sysevent_client *)arg; 667 mod = (module_t *)scp->client_data; 668 669 (void) mutex_lock(&scp->client_lock); 670 for (;;) { 671 while (scp->eventq == NULL) { 672 673 /* 674 * Client has been suspended or unloaded, go no further. 675 */ 676 if (fini_pending) { 677 scp->client_flags &= ~SE_CLIENT_THR_RUNNING; 678 syseventd_print(3, "Client %d delivery thread " 679 "exiting flags: 0X%x\n", 680 scp->client_num, scp->client_flags); 681 (void) mutex_unlock(&scp->client_lock); 682 return; 683 } 684 685 (void) cond_wait(&scp->client_cv, &scp->client_lock); 686 687 } 688 689 /* 690 * Process events from the head of the eventq, eventq is locked 691 * going into the processing. 692 */ 693 eventq = scp->eventq; 694 while (eventq != NULL) { 695 d_pkg = eventq->d_pkg; 696 d_pkg->completion_state = SE_OUTSTANDING; 697 scp->eventq = eventq->next; 698 free(eventq); 699 (void) mutex_unlock(&scp->client_lock); 700 701 702 flag = error = 0; 703 ev = d_pkg->ev; 704 705 syseventd_print(3, "Start delivery for client %d " 706 "with retry count %d\n", 707 scp->client_num, d_pkg->retry_count); 708 709 /* 710 * Retry limit has been reached by this client, indicate 711 * that no further retries are allowed 712 */ 713 for (i = 0; i <= scp->retry_limit; ++i) { 714 if (i == scp->retry_limit) 715 flag = SE_NO_RETRY; 716 717 /* Start the clock for the event delivery */ 718 d_pkg->start_time = gethrtime(); 719 720 syseventd_print(9, "Deliver to module client " 721 "%s\n", mod->name); 722 723 error = mod->deliver_event(ev, flag); 724 725 /* Can not allow another retry */ 726 if (i == scp->retry_limit) 727 error = 0; 728 729 /* Stop the clock */ 730 now = gethrtime(); 731 732 /* 733 * Suspend event processing and drain the 734 * event q for latent clients 735 */ 736 if (now - d_pkg->start_time > 737 ((hrtime_t)SE_TIMEOUT * NANOSEC)) { 738 syseventd_print(1, "Unresponsive " 739 "client %d: Draining eventq and " 740 "suspending event delivery\n", 741 scp->client_num); 742 (void) mutex_lock(&scp->client_lock); 743 scp->client_flags &= 744 ~SE_CLIENT_THR_RUNNING; 745 scp->client_flags |= 746 SE_CLIENT_SUSPENDED; 747 748 /* Cleanup current event */ 749 d_pkg->completion_status = EFAULT; 750 d_pkg->completion_state = SE_COMPLETE; 751 (void) sema_post( 752 d_pkg->completion_sema); 753 754 /* 755 * Drain the remaining events from the 756 * queue. 757 */ 758 drain_eventq(scp, EINVAL); 759 (void) mutex_unlock(&scp->client_lock); 760 return; 761 } 762 763 /* Event delivery retry requested */ 764 if (fini_pending || error != EAGAIN) { 765 break; 766 } else { 767 (void) sleep(SE_RETRY_TIME); 768 } 769 } 770 771 (void) mutex_lock(&scp->client_lock); 772 d_pkg->completion_status = error; 773 d_pkg->completion_state = SE_COMPLETE; 774 (void) sema_post(d_pkg->completion_sema); 775 syseventd_print(3, "Completed delivery with " 776 "error %d\n", error); 777 eventq = scp->eventq; 778 } 779 780 syseventd_print(3, "No more events to process for client %d\n", 781 scp->client_num); 782 783 /* Return if this was a synchronous delivery */ 784 if (!SE_CLIENT_IS_THR_RUNNING(scp)) { 785 (void) mutex_unlock(&scp->client_lock); 786 return; 787 } 788 789 } 790 } 791 792 /* 793 * client_deliver_event - Client specific event delivery 794 * This routine will allocate and initialize the 795 * neccessary per-client dispatch data. 796 * 797 * If the eventq is not empty, it may be assumed that 798 * a delivery thread exists for this client and the 799 * dispatch data is appended to the eventq. 800 * 801 * The dispatch package is freed by the event completion 802 * thread (event_completion_thr) and the eventq entry 803 * is freed by the event delivery thread. 804 */ 805 static struct event_dispatch_pkg * 806 client_deliver_event(struct sysevent_client *scp, sysevent_t *ev, 807 sema_t *completion_sema) 808 { 809 size_t ev_sz = sysevent_get_size(ev); 810 struct event_dispatchq *newq, *tmp; 811 struct event_dispatch_pkg *d_pkg; 812 813 syseventd_print(3, "client_deliver_event: id 0x%llx size %d\n", 814 (longlong_t)sysevent_get_seq(ev), ev_sz); 815 if (debug_level == 9) { 816 se_print(stdout, ev); 817 } 818 819 /* 820 * Check for suspended client 821 */ 822 (void) mutex_lock(&scp->client_lock); 823 if (SE_CLIENT_IS_SUSPENDED(scp) || !SE_CLIENT_IS_THR_RUNNING(scp)) { 824 (void) mutex_unlock(&scp->client_lock); 825 return (NULL); 826 } 827 828 /* 829 * Allocate a new dispatch package and eventq entry 830 */ 831 newq = (struct event_dispatchq *)malloc( 832 sizeof (struct event_dispatchq)); 833 if (newq == NULL) { 834 (void) mutex_unlock(&scp->client_lock); 835 return (NULL); 836 } 837 838 d_pkg = (struct event_dispatch_pkg *)malloc( 839 sizeof (struct event_dispatch_pkg)); 840 if (d_pkg == NULL) { 841 free(newq); 842 (void) mutex_unlock(&scp->client_lock); 843 return (NULL); 844 } 845 846 /* Initialize the dispatch package */ 847 d_pkg->scp = scp; 848 d_pkg->retry_count = 0; 849 d_pkg->completion_status = 0; 850 d_pkg->completion_state = SE_NOT_DISPATCHED; 851 d_pkg->completion_sema = completion_sema; 852 d_pkg->ev = ev; 853 newq->d_pkg = d_pkg; 854 newq->next = NULL; 855 856 if (scp->eventq != NULL) { 857 858 /* Add entry to the end of the eventq */ 859 tmp = scp->eventq; 860 while (tmp->next != NULL) 861 tmp = tmp->next; 862 tmp->next = newq; 863 } else { 864 /* event queue empty, wakeup delivery thread */ 865 scp->eventq = newq; 866 (void) cond_signal(&scp->client_cv); 867 } 868 (void) mutex_unlock(&scp->client_lock); 869 870 return (d_pkg); 871 } 872 873 /* 874 * event_completion_thr - Event completion thread. This thread routine 875 * waits for all client delivery thread to complete 876 * delivery of a particular event. 877 */ 878 static void 879 event_completion_thr() 880 { 881 int ret, i, client_count, ok_to_free; 882 sysevent_id_t eid; 883 struct sysevent_client *scp; 884 struct ev_completion *ev_comp; 885 struct event_dispatchq *dispatchq; 886 struct event_dispatch_pkg *d_pkg; 887 888 (void) mutex_lock(&ev_comp_lock); 889 for (;;) { 890 while (event_compq == NULL) { 891 (void) cond_wait(&event_comp_cv, &ev_comp_lock); 892 } 893 894 /* 895 * Process event completions from the head of the 896 * completion queue 897 */ 898 ev_comp = event_compq; 899 while (ev_comp) { 900 (void) mutex_unlock(&ev_comp_lock); 901 eid.eid_seq = sysevent_get_seq(ev_comp->ev); 902 sysevent_get_time(ev_comp->ev, &eid.eid_ts); 903 client_count = ev_comp->client_count; 904 ok_to_free = 1; 905 906 syseventd_print(3, "Wait for event completion of " 907 "event 0X%llx on %d clients\n", 908 eid.eid_seq, client_count); 909 910 while (client_count) { 911 syseventd_print(9, "Waiting for %d clients on " 912 "event id 0X%llx\n", client_count, 913 eid.eid_seq); 914 915 (void) sema_wait(&ev_comp->client_sema); 916 --client_count; 917 } 918 919 syseventd_print(3, "Cleaning up clients for event " 920 "0X%llx\n", eid.eid_seq); 921 dispatchq = ev_comp->dispatch_list; 922 while (dispatchq != NULL) { 923 d_pkg = dispatchq->d_pkg; 924 scp = d_pkg->scp; 925 926 if (d_pkg->completion_status == EAGAIN) 927 ok_to_free = 0; 928 929 syseventd_print(4, "Delivery of 0X%llx " 930 "complete for client %d retry count %d " 931 "status %d\n", eid.eid_seq, 932 scp->client_num, 933 d_pkg->retry_count, 934 d_pkg->completion_status); 935 936 free(d_pkg); 937 ev_comp->dispatch_list = dispatchq->next; 938 free(dispatchq); 939 dispatchq = ev_comp->dispatch_list; 940 } 941 942 if (ok_to_free) { 943 for (i = 0; i < MAX_MODCTL_RETRY; ++i) { 944 if ((ret = modctl(MODEVENTS, 945 (uintptr_t)MODEVENTS_FREEDATA, 946 (uintptr_t)&eid, NULL, 947 NULL, 0)) != 0) { 948 syseventd_print(1, "attempting " 949 "to free event 0X%llx\n", 950 eid.eid_seq); 951 952 /* 953 * Kernel may need time to 954 * move this event buffer to 955 * the sysevent sent queue 956 */ 957 (void) sleep(1); 958 } else { 959 break; 960 } 961 } 962 if (ret) { 963 syseventd_print(1, "Unable to free " 964 "event 0X%llx from the " 965 "kernel\n", eid.eid_seq); 966 } 967 } else { 968 syseventd_print(1, "Not freeing event 0X%llx\n", 969 eid.eid_seq); 970 } 971 972 syseventd_print(2, "Event delivery complete for id " 973 "0X%llx\n", eid.eid_seq); 974 975 (void) mutex_lock(&ev_comp_lock); 976 event_compq = ev_comp->next; 977 free(ev_comp->ev); 978 free(ev_comp); 979 ev_comp = event_compq; 980 (void) sema_post(&sema_resource); 981 } 982 983 /* 984 * Event completion queue is empty, signal possible unload 985 * operation 986 */ 987 (void) cond_signal(&event_comp_cv); 988 989 syseventd_print(3, "No more events\n"); 990 } 991 } 992 993 /* 994 * dispatch - Dispatch the current event buffer to all valid SLM clients. 995 */ 996 static int 997 dispatch(void) 998 { 999 int ev_sz, i, client_count = 0; 1000 sysevent_t *new_ev; 1001 sysevent_id_t eid; 1002 struct ev_completion *ev_comp, *tmp; 1003 struct event_dispatchq *dispatchq, *client_list; 1004 struct event_dispatch_pkg *d_pkg; 1005 1006 /* Check for module unload operation */ 1007 if (rw_tryrdlock(&mod_unload_lock) != 0) { 1008 syseventd_print(2, "unload in progress abort delivery\n"); 1009 (void) sema_post(&sema_eventbuf); 1010 (void) sema_post(&sema_resource); 1011 return (0); 1012 } 1013 1014 syseventd_print(3, "deliver dispatch buffer %d", dispatch_buf); 1015 eid.eid_seq = sysevent_get_seq(eventbuf[dispatch_buf]); 1016 sysevent_get_time(eventbuf[dispatch_buf], &eid.eid_ts); 1017 syseventd_print(3, "deliver msg id: 0x%llx\n", eid.eid_seq); 1018 1019 /* 1020 * ev_comp is used to hold event completion data. It is freed 1021 * by the event completion thread (event_completion_thr). 1022 */ 1023 ev_comp = (struct ev_completion *) 1024 malloc(sizeof (struct ev_completion)); 1025 if (ev_comp == NULL) { 1026 (void) rw_unlock(&mod_unload_lock); 1027 syseventd_print(1, "Can not allocate event completion buffer " 1028 "for event id 0X%llx\n", eid.eid_seq); 1029 return (EAGAIN); 1030 } 1031 ev_comp->dispatch_list = NULL; 1032 ev_comp->next = NULL; 1033 (void) sema_init(&ev_comp->client_sema, 0, USYNC_THREAD, NULL); 1034 1035 ev_sz = sysevent_get_size(eventbuf[dispatch_buf]); 1036 new_ev = calloc(1, ev_sz); 1037 if (new_ev == NULL) { 1038 free(ev_comp); 1039 (void) rw_unlock(&mod_unload_lock); 1040 syseventd_print(1, "Can not allocate new event buffer " 1041 "for event id 0X%llx\n", eid.eid_seq); 1042 return (EAGAIN); 1043 } 1044 1045 1046 /* 1047 * For long messages, copy additional data from kernel 1048 */ 1049 if (ev_sz > LOGEVENT_BUFSIZE) { 1050 int ret = 0; 1051 1052 /* Ok to release eventbuf for next event buffer from kernel */ 1053 (void) sema_post(&sema_eventbuf); 1054 1055 for (i = 0; i < MAX_MODCTL_RETRY; ++i) { 1056 if ((ret = modctl(MODEVENTS, 1057 (uintptr_t)MODEVENTS_GETDATA, 1058 (uintptr_t)&eid, 1059 (uintptr_t)ev_sz, 1060 (uintptr_t)new_ev, 0)) 1061 == 0) 1062 break; 1063 else 1064 (void) sleep(1); 1065 } 1066 if (ret) { 1067 syseventd_print(1, "GET_DATA failed for 0X%llx:%llx\n", 1068 eid.eid_ts, eid.eid_seq); 1069 free(new_ev); 1070 free(ev_comp); 1071 (void) rw_unlock(&mod_unload_lock); 1072 return (EAGAIN); 1073 } 1074 } else { 1075 (void) bcopy(eventbuf[dispatch_buf], new_ev, ev_sz); 1076 /* Ok to release eventbuf for next event buffer from kernel */ 1077 (void) sema_post(&sema_eventbuf); 1078 } 1079 1080 1081 /* 1082 * Deliver a copy of eventbuf to clients so 1083 * eventbuf can be used for the next message 1084 */ 1085 for (i = 0; i < MAX_SLM; ++i) { 1086 1087 /* Don't bother for suspended or unloaded clients */ 1088 if (!SE_CLIENT_IS_LOADED(sysevent_client_tbl[i]) || 1089 SE_CLIENT_IS_SUSPENDED(sysevent_client_tbl[i])) 1090 continue; 1091 1092 /* 1093 * Allocate event dispatch queue entry. All queue entries 1094 * are freed by the event completion thread as client 1095 * delivery completes. 1096 */ 1097 dispatchq = (struct event_dispatchq *)malloc( 1098 sizeof (struct event_dispatchq)); 1099 if (dispatchq == NULL) { 1100 syseventd_print(1, "Can not allocate dispatch q " 1101 "for event id 0X%llx client %d\n", eid.eid_seq, i); 1102 continue; 1103 } 1104 dispatchq->next = NULL; 1105 1106 /* Initiate client delivery */ 1107 d_pkg = client_deliver_event(sysevent_client_tbl[i], 1108 new_ev, &ev_comp->client_sema); 1109 if (d_pkg == NULL) { 1110 syseventd_print(1, "Can not allocate dispatch " 1111 "package for event id 0X%llx client %d\n", 1112 eid.eid_seq, i); 1113 free(dispatchq); 1114 continue; 1115 } 1116 dispatchq->d_pkg = d_pkg; 1117 ++client_count; 1118 1119 if (ev_comp->dispatch_list == NULL) { 1120 ev_comp->dispatch_list = dispatchq; 1121 client_list = dispatchq; 1122 } else { 1123 client_list->next = dispatchq; 1124 client_list = client_list->next; 1125 } 1126 } 1127 1128 ev_comp->client_count = client_count; 1129 ev_comp->ev = new_ev; 1130 1131 (void) mutex_lock(&ev_comp_lock); 1132 1133 if (event_compq == NULL) { 1134 syseventd_print(3, "Wakeup event completion thread for " 1135 "id 0X%llx\n", eid.eid_seq); 1136 event_compq = ev_comp; 1137 (void) cond_signal(&event_comp_cv); 1138 } else { 1139 1140 /* Add entry to the end of the event completion queue */ 1141 tmp = event_compq; 1142 while (tmp->next != NULL) 1143 tmp = tmp->next; 1144 tmp->next = ev_comp; 1145 syseventd_print(3, "event added to completion queue for " 1146 "id 0X%llx\n", eid.eid_seq); 1147 } 1148 (void) mutex_unlock(&ev_comp_lock); 1149 (void) rw_unlock(&mod_unload_lock); 1150 1151 return (0); 1152 } 1153 1154 #define MODULE_DIR_HW "/usr/platform/%s/lib/sysevent/modules/" 1155 #define MODULE_DIR_GEN "/usr/lib/sysevent/modules/" 1156 #define MOD_DIR_NUM 3 1157 static char dirname[MOD_DIR_NUM][MAXPATHLEN]; 1158 1159 static char * 1160 dir_num2name(int dirnum) 1161 { 1162 char infobuf[MAXPATHLEN]; 1163 1164 if (dirnum >= MOD_DIR_NUM) 1165 return (NULL); 1166 1167 if (dirname[0][0] == '\0') { 1168 if (sysinfo(SI_PLATFORM, infobuf, MAXPATHLEN) == -1) { 1169 syseventd_print(1, "dir_num2name: " 1170 "sysinfo error %s\n", strerror(errno)); 1171 return (NULL); 1172 } else if (snprintf(dirname[0], sizeof (dirname[0]), 1173 MODULE_DIR_HW, infobuf) >= sizeof (dirname[0])) { 1174 syseventd_print(1, "dir_num2name: " 1175 "platform name too long: %s\n", 1176 infobuf); 1177 return (NULL); 1178 } 1179 if (sysinfo(SI_MACHINE, infobuf, MAXPATHLEN) == -1) { 1180 syseventd_print(1, "dir_num2name: " 1181 "sysinfo error %s\n", strerror(errno)); 1182 return (NULL); 1183 } else if (snprintf(dirname[1], sizeof (dirname[1]), 1184 MODULE_DIR_HW, infobuf) >= sizeof (dirname[1])) { 1185 syseventd_print(1, "dir_num2name: " 1186 "machine name too long: %s\n", 1187 infobuf); 1188 return (NULL); 1189 } 1190 (void) strcpy(dirname[2], MODULE_DIR_GEN); 1191 } 1192 1193 return (dirname[dirnum]); 1194 } 1195 1196 1197 /* 1198 * load_modules - Load modules found in the common syseventd module directories 1199 * Modules that do not provide valid interfaces are rejected. 1200 */ 1201 static void 1202 load_modules(char *dirname) 1203 { 1204 int client_id; 1205 DIR *mod_dir; 1206 module_t *mod; 1207 struct dirent *entp; 1208 struct slm_mod_ops *mod_ops; 1209 struct sysevent_client *scp; 1210 1211 if (dirname == NULL) 1212 return; 1213 1214 /* Return silently if module directory does not exist */ 1215 if ((mod_dir = opendir(dirname)) == NULL) { 1216 syseventd_print(1, "Unable to open module directory %s: %s\n", 1217 dirname, strerror(errno)); 1218 return; 1219 } 1220 1221 syseventd_print(3, "loading modules from %s\n", dirname); 1222 1223 /* 1224 * Go through directory, looking for files ending with .so 1225 */ 1226 while ((entp = readdir(mod_dir)) != NULL) { 1227 void *dlh, *f; 1228 char *tmp, modpath[MAXPATHLEN]; 1229 1230 if (((tmp = strstr(entp->d_name, MODULE_SUFFIX)) == NULL) || 1231 (tmp[strlen(MODULE_SUFFIX)] != '\0')) { 1232 continue; 1233 } 1234 1235 if (snprintf(modpath, sizeof (modpath), "%s%s", 1236 dirname, entp->d_name) >= sizeof (modpath)) { 1237 syseventd_err_print(INIT_PATH_ERR, modpath); 1238 continue; 1239 } 1240 if ((dlh = dlopen(modpath, RTLD_LAZY)) == NULL) { 1241 syseventd_err_print(LOAD_MOD_DLOPEN_ERR, 1242 modpath, dlerror()); 1243 continue; 1244 } else if ((f = dlsym(dlh, EVENT_INIT)) == NULL) { 1245 syseventd_err_print(LOAD_MOD_NO_INIT, 1246 modpath, dlerror()); 1247 (void) dlclose(dlh); 1248 continue; 1249 } 1250 1251 mod = malloc(sizeof (*mod)); 1252 if (mod == NULL) { 1253 syseventd_err_print(LOAD_MOD_ALLOC_ERR, "mod", 1254 strerror(errno)); 1255 (void) dlclose(dlh); 1256 continue; 1257 } 1258 1259 mod->name = strdup(entp->d_name); 1260 if (mod->name == NULL) { 1261 syseventd_err_print(LOAD_MOD_ALLOC_ERR, "mod->name", 1262 strerror(errno)); 1263 (void) dlclose(dlh); 1264 free(mod); 1265 continue; 1266 } 1267 1268 mod->dlhandle = dlh; 1269 mod->event_mod_init = (struct slm_mod_ops *(*)())f; 1270 1271 /* load in other module functions */ 1272 mod->event_mod_fini = (void (*)())dlsym(dlh, EVENT_FINI); 1273 if (mod->event_mod_fini == NULL) { 1274 syseventd_err_print(LOAD_MOD_DLSYM_ERR, mod->name, 1275 dlerror()); 1276 free(mod->name); 1277 free(mod); 1278 (void) dlclose(dlh); 1279 continue; 1280 } 1281 1282 /* Call module init routine */ 1283 if ((mod_ops = mod->event_mod_init()) == NULL) { 1284 syseventd_err_print(LOAD_MOD_EINVAL, mod->name); 1285 free(mod->name); 1286 free(mod); 1287 (void) dlclose(dlh); 1288 continue; 1289 } 1290 if (mod_ops->major_version != SE_MAJOR_VERSION) { 1291 syseventd_err_print(LOAD_MOD_VERSION_MISMATCH, 1292 mod->name, SE_MAJOR_VERSION, 1293 mod_ops->major_version); 1294 mod->event_mod_fini(); 1295 free(mod->name); 1296 free(mod); 1297 (void) dlclose(dlh); 1298 continue; 1299 } 1300 1301 mod->deliver_event = mod_ops->deliver_event; 1302 /* Add module entry to client list */ 1303 if ((client_id = insert_client((void *)mod, SLM_CLIENT, 1304 (mod_ops->retry_limit <= SE_MAX_RETRY_LIMIT ? 1305 mod_ops->retry_limit : SE_MAX_RETRY_LIMIT))) < 0) { 1306 syseventd_err_print(LOAD_MOD_ALLOC_ERR, "insert_client", 1307 strerror(errno)); 1308 mod->event_mod_fini(); 1309 free(mod->name); 1310 free(mod); 1311 (void) dlclose(dlh); 1312 continue; 1313 } 1314 1315 scp = sysevent_client_tbl[client_id]; 1316 ++concurrency_level; 1317 (void) thr_setconcurrency(concurrency_level); 1318 if (thr_create(NULL, 0, 1319 (void *(*)(void *))client_deliver_event_thr, 1320 (void *)scp, THR_BOUND, &scp->tid) != 0) { 1321 1322 syseventd_err_print(LOAD_MOD_ALLOC_ERR, "insert_client", 1323 strerror(errno)); 1324 mod->event_mod_fini(); 1325 free(mod->name); 1326 free(mod); 1327 (void) dlclose(dlh); 1328 continue; 1329 } 1330 scp->client_flags |= SE_CLIENT_THR_RUNNING; 1331 1332 syseventd_print(3, "loaded module %s\n", entp->d_name); 1333 } 1334 1335 (void) closedir(mod_dir); 1336 syseventd_print(3, "modules loaded\n"); 1337 } 1338 1339 /* 1340 * unload_modules - modules are unloaded prior to graceful shutdown or 1341 * before restarting the daemon upon receipt of 1342 * SIGHUP. 1343 */ 1344 static void 1345 unload_modules(int sig) 1346 { 1347 int i, count, done; 1348 module_t *mod; 1349 struct sysevent_client *scp; 1350 1351 /* 1352 * unload modules that are ready, skip those that have not 1353 * drained their event queues. 1354 */ 1355 count = done = 0; 1356 while (done < MAX_SLM) { 1357 /* Don't wait indefinitely for unresponsive clients */ 1358 if (sig != SIGHUP && count > SE_TIMEOUT) { 1359 break; 1360 } 1361 1362 done = 0; 1363 1364 /* Shutdown clients */ 1365 for (i = 0; i < MAX_SLM; ++i) { 1366 scp = sysevent_client_tbl[i]; 1367 if (mutex_trylock(&scp->client_lock) == 0) { 1368 if (scp->client_type != SLM_CLIENT || 1369 scp->client_data == NULL) { 1370 (void) mutex_unlock(&scp->client_lock); 1371 done++; 1372 continue; 1373 } 1374 } else { 1375 syseventd_print(3, "Skipping unload of " 1376 "client %d: client locked\n", 1377 scp->client_num); 1378 continue; 1379 } 1380 1381 /* 1382 * Drain the eventq and wait for delivery thread to 1383 * cleanly exit 1384 */ 1385 drain_eventq(scp, EAGAIN); 1386 (void) cond_signal(&scp->client_cv); 1387 (void) mutex_unlock(&scp->client_lock); 1388 (void) thr_join(scp->tid, NULL, NULL); 1389 1390 /* 1391 * It is now safe to unload the module 1392 */ 1393 mod = (module_t *)scp->client_data; 1394 syseventd_print(2, "Unload %s\n", mod->name); 1395 mod->event_mod_fini(); 1396 (void) dlclose(mod->dlhandle); 1397 free(mod->name); 1398 (void) mutex_lock(&client_tbl_lock); 1399 delete_client(i); 1400 (void) mutex_unlock(&client_tbl_lock); 1401 ++done; 1402 1403 } 1404 ++count; 1405 (void) sleep(1); 1406 } 1407 1408 /* 1409 * Wait for event completions 1410 */ 1411 syseventd_print(2, "waiting for event completions\n"); 1412 (void) mutex_lock(&ev_comp_lock); 1413 while (event_compq != NULL) { 1414 (void) cond_wait(&event_comp_cv, &ev_comp_lock); 1415 } 1416 (void) mutex_unlock(&ev_comp_lock); 1417 } 1418 1419 /* 1420 * syseventd_init - Called at daemon (re)start-up time to load modules 1421 * and kickstart the kernel delivery engine. 1422 */ 1423 static void 1424 syseventd_init() 1425 { 1426 int i, fd; 1427 char local_door_file[PATH_MAX + 1]; 1428 1429 fini_pending = 0; 1430 1431 concurrency_level = MIN_CONCURRENCY_LEVEL; 1432 (void) thr_setconcurrency(concurrency_level); 1433 1434 /* 1435 * Load client modules for event delivering 1436 */ 1437 for (i = 0; i < MOD_DIR_NUM; ++i) { 1438 load_modules(dir_num2name(i)); 1439 } 1440 1441 /* 1442 * Create kernel delivery door service 1443 */ 1444 syseventd_print(8, "Create a door for kernel upcalls\n"); 1445 if (snprintf(local_door_file, sizeof (local_door_file), "%s%s", 1446 root_dir, LOGEVENT_DOOR_UPCALL) >= sizeof (local_door_file)) { 1447 syseventd_err_print(INIT_PATH_ERR, local_door_file); 1448 syseventd_exit(5); 1449 } 1450 1451 /* 1452 * Remove door file for robustness. 1453 */ 1454 if (unlink(local_door_file) != 0) 1455 syseventd_print(8, "Unlink of %s failed.\n", local_door_file); 1456 1457 fd = open(local_door_file, O_CREAT|O_RDWR, S_IREAD|S_IWRITE); 1458 if ((fd == -1) && (errno != EEXIST)) { 1459 syseventd_err_print(INIT_OPEN_DOOR_ERR, strerror(errno)); 1460 syseventd_exit(5); 1461 } 1462 (void) close(fd); 1463 1464 upcall_door = door_create(door_upcall, NULL, 1465 DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 1466 if (upcall_door == -1) { 1467 syseventd_err_print(INIT_CREATE_DOOR_ERR, strerror(errno)); 1468 syseventd_exit(5); 1469 } 1470 1471 (void) fdetach(local_door_file); 1472 retry: 1473 if (fattach(upcall_door, local_door_file) != 0) { 1474 if (errno == EBUSY) 1475 goto retry; 1476 syseventd_err_print(INIT_FATTACH_ERR, strerror(errno)); 1477 (void) door_revoke(upcall_door); 1478 syseventd_exit(5); 1479 } 1480 1481 /* 1482 * Tell kernel the door name and start delivery 1483 */ 1484 syseventd_print(2, 1485 "local_door_file = %s\n", local_door_file); 1486 if (modctl(MODEVENTS, 1487 (uintptr_t)MODEVENTS_SET_DOOR_UPCALL_FILENAME, 1488 (uintptr_t)local_door_file, NULL, NULL, 0) < 0) { 1489 syseventd_err_print(INIT_DOOR_NAME_ERR, strerror(errno)); 1490 syseventd_exit(6); 1491 } 1492 1493 door_upcall_retval = 0; 1494 1495 if (modctl(MODEVENTS, (uintptr_t)MODEVENTS_FLUSH, NULL, NULL, NULL, 0) 1496 < 0) { 1497 syseventd_err_print(KERNEL_REPLAY_ERR, strerror(errno)); 1498 syseventd_exit(7); 1499 } 1500 } 1501 1502 /* 1503 * syseventd_fini - shut down daemon, but do not exit 1504 */ 1505 static void 1506 syseventd_fini(int sig) 1507 { 1508 /* 1509 * Indicate that event queues should be drained and no 1510 * additional events be accepted 1511 */ 1512 fini_pending = 1; 1513 1514 /* Close the kernel event door to halt delivery */ 1515 (void) door_revoke(upcall_door); 1516 1517 syseventd_print(1, "Unloading modules\n"); 1518 (void) rw_wrlock(&mod_unload_lock); 1519 unload_modules(sig); 1520 (void) rw_unlock(&mod_unload_lock); 1521 1522 } 1523 1524 /* 1525 * enter_daemon_lock - lock the daemon file lock 1526 * 1527 * Use an advisory lock to ensure that only one daemon process is active 1528 * in the system at any point in time. If the lock is held by another 1529 * process, do not block but return the pid owner of the lock to the 1530 * caller immediately. The lock is cleared if the holding daemon process 1531 * exits for any reason even if the lock file remains, so the daemon can 1532 * be restarted if necessary. The lock file is DAEMON_LOCK_FILE. 1533 */ 1534 static pid_t 1535 enter_daemon_lock(void) 1536 { 1537 struct flock lock; 1538 1539 syseventd_print(8, "enter_daemon_lock: lock file = %s\n", 1540 DAEMON_LOCK_FILE); 1541 1542 if (snprintf(local_lock_file, sizeof (local_lock_file), "%s%s", 1543 root_dir, DAEMON_LOCK_FILE) >= sizeof (local_lock_file)) { 1544 syseventd_err_print(INIT_PATH_ERR, local_lock_file); 1545 syseventd_exit(8); 1546 } 1547 daemon_lock_fd = open(local_lock_file, O_CREAT|O_RDWR, 0644); 1548 if (daemon_lock_fd < 0) { 1549 syseventd_err_print(INIT_LOCK_OPEN_ERR, 1550 local_lock_file, strerror(errno)); 1551 syseventd_exit(8); 1552 } 1553 1554 lock.l_type = F_WRLCK; 1555 lock.l_whence = SEEK_SET; 1556 lock.l_start = 0; 1557 lock.l_len = 0; 1558 1559 if (fcntl(daemon_lock_fd, F_SETLK, &lock) == -1) { 1560 if (fcntl(daemon_lock_fd, F_GETLK, &lock) == -1) { 1561 syseventd_err_print(INIT_LOCK_ERR, 1562 local_lock_file, strerror(errno)); 1563 exit(2); 1564 } 1565 return (lock.l_pid); 1566 } 1567 hold_daemon_lock = 1; 1568 1569 return (getpid()); 1570 } 1571 1572 /* 1573 * exit_daemon_lock - release the daemon file lock 1574 */ 1575 static void 1576 exit_daemon_lock(void) 1577 { 1578 struct flock lock; 1579 1580 lock.l_type = F_UNLCK; 1581 lock.l_whence = SEEK_SET; 1582 lock.l_start = 0; 1583 lock.l_len = 0; 1584 1585 if (fcntl(daemon_lock_fd, F_SETLK, &lock) == -1) { 1586 syseventd_err_print(INIT_UNLOCK_ERR, 1587 local_lock_file, strerror(errno)); 1588 } 1589 1590 if (close(daemon_lock_fd) == -1) { 1591 syseventd_err_print(INIT_LOCK_CLOSE_ERR, 1592 local_lock_file, strerror(errno)); 1593 exit(-1); 1594 } 1595 } 1596 1597 /* 1598 * syseventd_err_print - print error messages to the terminal if not 1599 * yet daemonized or to syslog. 1600 */ 1601 /*PRINTFLIKE1*/ 1602 void 1603 syseventd_err_print(char *message, ...) 1604 { 1605 va_list ap; 1606 1607 (void) mutex_lock(&err_mutex); 1608 va_start(ap, message); 1609 1610 if (logflag) { 1611 (void) vsyslog(LOG_ERR, message, ap); 1612 } else { 1613 (void) fprintf(stderr, "%s: ", prog); 1614 (void) vfprintf(stderr, message, ap); 1615 } 1616 va_end(ap); 1617 (void) mutex_unlock(&err_mutex); 1618 } 1619 1620 /* 1621 * syseventd_print - print messages to the terminal or to syslog 1622 * the following levels are implemented: 1623 * 1624 * 1 - transient errors that does not affect normal program flow 1625 * 2 - upcall/dispatch interaction 1626 * 3 - program flow trace as each message goes through the daemon 1627 * 8 - all the nit-gritty details of startup and shutdown 1628 * 9 - very verbose event flow tracing (no daemonization of syseventd) 1629 * 1630 */ 1631 /*PRINTFLIKE2*/ 1632 void 1633 syseventd_print(int level, char *message, ...) 1634 { 1635 va_list ap; 1636 static int newline = 1; 1637 1638 if (level > debug_level) { 1639 return; 1640 } 1641 1642 (void) mutex_lock(&err_mutex); 1643 va_start(ap, message); 1644 if (logflag) { 1645 (void) syslog(LOG_DEBUG, "%s[%ld]: ", 1646 prog, getpid()); 1647 (void) vsyslog(LOG_DEBUG, message, ap); 1648 } else { 1649 if (newline) { 1650 (void) fprintf(stdout, "%s[%ld]: ", 1651 prog, getpid()); 1652 (void) vfprintf(stdout, message, ap); 1653 } else { 1654 (void) vfprintf(stdout, message, ap); 1655 } 1656 } 1657 if (message[strlen(message)-1] == '\n') { 1658 newline = 1; 1659 } else { 1660 newline = 0; 1661 } 1662 va_end(ap); 1663 (void) mutex_unlock(&err_mutex); 1664 } 1665