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