comparison usr/src/lib/libsysevent/libsysevent.c @ 12979:ab9ae749152f

PSARC/2009/617 Software Events Notification Parameters CLI PSARC/2009/618 snmp-notify: SNMP Notification Daemon for Software Events PSARC/2009/619 smtp-notify: Email Notification Daemon for Software Events PSARC/2010/225 fmd for non-global Solaris zones PSARC/2010/226 Solaris Instance UUID PSARC/2010/227 nvlist_nvflag(3NVPAIR) PSARC/2010/228 libfmevent additions PSARC/2010/257 sysevent_evc_setpropnvl and sysevent_evc_getpropnvl PSARC/2010/265 FMRI and FMA Event Stabilty, 'ireport' category 1 event class, and the 'sw' FMRI scheme PSARC/2010/278 FMA/SMF integration: instance state transitions PSARC/2010/279 Modelling panics within FMA PSARC/2010/290 logadm.conf upgrade 6392476 fmdump needs to pretty-print 6393375 userland ereport/ireport event generation interfaces 6445732 Add email notification agent for FMA and software events 6804168 RFE: Allow an efficient means to monitor SMF services status changes 6866661 scf_values_destroy(3SCF) will segfault if is passed NULL 6884709 Add snmp notification agent for FMA and software events 6884712 Add private interface to tap into libfmd_msg macro expansion capabilities 6897919 fmd to run in a non-global zone 6897937 fmd use of non-private doors is not safe 6900081 add a UUID to Solaris kernel image for use in crashdump identification 6914884 model panic events as a defect diagnosis in FMA 6944862 fmd_case_open_uuid, fmd_case_uuisresolved, fmd_nvl_create_defect 6944866 log legacy sysevents in fmd 6944867 enumerate svc scheme in topo 6944868 software-diagnosis and software-response fmd modules 6944870 model SMF maintenance state as a defect diagnosis in FMA 6944876 savecore runs in foreground for systems with zfs root and dedicated dump 6965796 Implement notification parameters for SMF state transitions and FMA events 6968287 SUN-FM-MIB.mib needs to be updated to reflect Oracle information 6972331 logadm.conf upgrade PSARC/2010/290
author Gavin Maltby <gavin.maltby@oracle.com>
date Fri, 30 Jul 2010 17:04:17 +1000
parents 8f30d0e611c6
children
comparison
equal deleted inserted replaced
12978:19d842faf8e4 12979:ab9ae749152f
18 * 18 *
19 * CDDL HEADER END 19 * CDDL HEADER END
20 */ 20 */
21 21
22 /* 22 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
25 */ 24 */
26 25
27 #include <stdio.h> 26 #include <stdio.h>
28 #include <fcntl.h> 27 #include <fcntl.h>
29 #include <errno.h> 28 #include <errno.h>
33 #include <stdlib.h> 32 #include <stdlib.h>
34 #include <string.h> 33 #include <string.h>
35 #include <strings.h> 34 #include <strings.h>
36 #include <synch.h> 35 #include <synch.h>
37 #include <pthread.h> 36 #include <pthread.h>
37 #include <signal.h>
38 #include <thread.h> 38 #include <thread.h>
39 #include <libnvpair.h> 39 #include <libnvpair.h>
40 #include <assert.h> 40 #include <assert.h>
41 #include <sys/stat.h> 41 #include <sys/stat.h>
42 #include <sys/types.h> 42 #include <sys/types.h>
762 subscriber_priv_t *sub_info; 762 subscriber_priv_t *sub_info;
763 sysevent_queue_t *evqp; 763 sysevent_queue_t *evqp;
764 764
765 sub_info = (subscriber_priv_t *)SH_PRIV_DATA(shp); 765 sub_info = (subscriber_priv_t *)SH_PRIV_DATA(shp);
766 766
767 /* See hack alert in sysevent_bind_subscriber_cmn */
768 if (sub_info->sp_handler_tid == NULL)
769 sub_info->sp_handler_tid = thr_self();
770
767 (void) mutex_lock(&sub_info->sp_qlock); 771 (void) mutex_lock(&sub_info->sp_qlock);
768 for (;;) { 772 for (;;) {
769 while (sub_info->sp_evq_head == NULL && SH_BOUND(shp)) { 773 while (sub_info->sp_evq_head == NULL && SH_BOUND(shp)) {
770 (void) cond_wait(&sub_info->sp_cv, &sub_info->sp_qlock); 774 (void) cond_wait(&sub_info->sp_cv, &sub_info->sp_qlock);
771 } 775 }
2036 (void) mutex_unlock(SH_LOCK(shp)); 2040 (void) mutex_unlock(SH_LOCK(shp));
2037 errno = error; 2041 errno = error;
2038 return (-1); 2042 return (-1);
2039 } 2043 }
2040 2044
2041 /* 2045 static pthread_once_t xdoor_thrattr_once = PTHREAD_ONCE_INIT;
2042 * sysevent_bind_subscriber - Bind an event receiver to an event channel 2046 static pthread_attr_t xdoor_thrattr;
2043 */ 2047
2044 int 2048 static void
2045 sysevent_bind_subscriber(sysevent_handle_t *shp, 2049 xdoor_thrattr_init(void)
2046 void (*event_handler)(sysevent_t *ev)) 2050 {
2051 (void) pthread_attr_init(&xdoor_thrattr);
2052 (void) pthread_attr_setdetachstate(&xdoor_thrattr,
2053 PTHREAD_CREATE_DETACHED);
2054 (void) pthread_attr_setscope(&xdoor_thrattr, PTHREAD_SCOPE_SYSTEM);
2055 }
2056
2057 static int
2058 xdoor_server_create(door_info_t *dip, void *(*startf)(void *),
2059 void *startfarg, void *cookie)
2060 {
2061 struct sysevent_subattr_impl *xsa = cookie;
2062 pthread_attr_t *thrattr;
2063 sigset_t oset;
2064 int err;
2065
2066 if (xsa->xs_thrcreate) {
2067 return (xsa->xs_thrcreate(dip, startf, startfarg,
2068 xsa->xs_thrcreate_cookie));
2069 }
2070
2071 if (xsa->xs_thrattr == NULL) {
2072 (void) pthread_once(&xdoor_thrattr_once, xdoor_thrattr_init);
2073 thrattr = &xdoor_thrattr;
2074 } else {
2075 thrattr = xsa->xs_thrattr;
2076 }
2077
2078 (void) pthread_sigmask(SIG_SETMASK, &xsa->xs_sigmask, &oset);
2079 err = pthread_create(NULL, thrattr, startf, startfarg);
2080 (void) pthread_sigmask(SIG_SETMASK, &oset, NULL);
2081
2082 return (err == 0 ? 1 : -1);
2083 }
2084
2085 static void
2086 xdoor_server_setup(void *cookie)
2087 {
2088 struct sysevent_subattr_impl *xsa = cookie;
2089
2090 if (xsa->xs_thrsetup) {
2091 xsa->xs_thrsetup(xsa->xs_thrsetup_cookie);
2092 } else {
2093 (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
2094 (void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
2095 }
2096 }
2097
2098 static int
2099 sysevent_bind_subscriber_cmn(sysevent_handle_t *shp,
2100 void (*event_handler)(sysevent_t *ev),
2101 sysevent_subattr_t *subattr)
2047 { 2102 {
2048 int fd = -1; 2103 int fd = -1;
2049 int error = 0; 2104 int error = 0;
2050 uint32_t sub_id = 0; 2105 uint32_t sub_id = 0;
2051 char door_name[MAXPATHLEN]; 2106 char door_name[MAXPATHLEN];
2052 subscriber_priv_t *sub_info; 2107 subscriber_priv_t *sub_info;
2108 int created;
2109 struct sysevent_subattr_impl *xsa =
2110 (struct sysevent_subattr_impl *)subattr;
2053 2111
2054 if (shp == NULL || event_handler == NULL) { 2112 if (shp == NULL || event_handler == NULL) {
2055 errno = EINVAL; 2113 errno = EINVAL;
2056 return (-1); 2114 return (-1);
2057 } 2115 }
2122 /* 2180 /*
2123 * Create the sysevent door service for this client. 2181 * Create the sysevent door service for this client.
2124 * syseventd will use this door service to propagate 2182 * syseventd will use this door service to propagate
2125 * events to the client. 2183 * events to the client.
2126 */ 2184 */
2127 if ((SH_DOOR_DESC(shp) = door_create(event_deliver_service, 2185 if (subattr == NULL) {
2128 (void *)shp, DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) { 2186 SH_DOOR_DESC(shp) = door_create(event_deliver_service,
2187 (void *)shp, DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
2188 } else {
2189 SH_DOOR_DESC(shp) = door_xcreate(event_deliver_service,
2190 (void *)shp,
2191 DOOR_REFUSE_DESC | DOOR_NO_CANCEL | DOOR_NO_DEPLETION_CB,
2192 xdoor_server_create, xdoor_server_setup,
2193 (void *)subattr, 1);
2194 }
2195
2196 if (SH_DOOR_DESC(shp) == -1) {
2129 dprint("sysevent_bind_subscriber: door create failed: " 2197 dprint("sysevent_bind_subscriber: door create failed: "
2130 "%s\n", strerror(errno)); 2198 "%s\n", strerror(errno));
2131 error = EFAULT; 2199 error = EFAULT;
2132 goto fail; 2200 goto fail;
2133 } 2201 }
2149 2217
2150 SH_BOUND(shp) = 1; 2218 SH_BOUND(shp) = 1;
2151 SH_TYPE(shp) = SUBSCRIBER; 2219 SH_TYPE(shp) = SUBSCRIBER;
2152 SH_PRIV_DATA(shp) = (void *)sub_info; 2220 SH_PRIV_DATA(shp) = (void *)sub_info;
2153 2221
2154
2155 /* Create an event handler thread */ 2222 /* Create an event handler thread */
2156 if (thr_create(NULL, NULL, (void *(*)(void *))subscriber_event_handler, 2223 if (xsa == NULL || xsa->xs_thrcreate == NULL) {
2157 shp, THR_BOUND, &sub_info->sp_handler_tid) != 0) { 2224 created = thr_create(NULL, NULL,
2225 (void *(*)(void *))subscriber_event_handler,
2226 shp, THR_BOUND, &sub_info->sp_handler_tid) == 0;
2227 } else {
2228 /*
2229 * A terrible hack. We will use the extended private
2230 * door thread creation function the caller passed in to
2231 * create the event handler thread. That function will
2232 * be called with our chosen thread start function and arg
2233 * instead of the usual libc-provided ones, but that's ok
2234 * as it is required to use them verbatim anyway. We will
2235 * pass a NULL door_info_t pointer to the function - so
2236 * callers depending on this hack had better be prepared
2237 * for that. All this allow the caller to rubberstamp
2238 * the created thread as it wishes. But we don't get
2239 * the created threadid with this, so we modify the
2240 * thread start function to stash it.
2241 */
2242
2243 created = xsa->xs_thrcreate(NULL,
2244 (void *(*)(void *))subscriber_event_handler,
2245 shp, xsa->xs_thrcreate_cookie) == 1;
2246 }
2247
2248 if (!created) {
2158 error = EFAULT; 2249 error = EFAULT;
2159 goto fail; 2250 goto fail;
2160 } 2251 }
2161 2252
2162 (void) mutex_unlock(SH_LOCK(shp)); 2253 (void) mutex_unlock(SH_LOCK(shp));
2188 2279
2189 return (-1); 2280 return (-1);
2190 } 2281 }
2191 2282
2192 /* 2283 /*
2284 * sysevent_bind_subscriber - Bind an event receiver to an event channel
2285 */
2286 int
2287 sysevent_bind_subscriber(sysevent_handle_t *shp,
2288 void (*event_handler)(sysevent_t *ev))
2289 {
2290 return (sysevent_bind_subscriber_cmn(shp, event_handler, NULL));
2291 }
2292
2293 /*
2294 * sysevent_bind_xsubscriber - Bind a subscriber using door_xcreate with
2295 * attributes specified.
2296 */
2297 int
2298 sysevent_bind_xsubscriber(sysevent_handle_t *shp,
2299 void (*event_handler)(sysevent_t *ev), sysevent_subattr_t *subattr)
2300 {
2301 return (sysevent_bind_subscriber_cmn(shp, event_handler, subattr));
2302 }
2303
2304 /*
2193 * sysevent_register_event - register an event class and associated subclasses 2305 * sysevent_register_event - register an event class and associated subclasses
2194 * for an event subscriber 2306 * for an event subscriber
2195 */ 2307 */
2196 int 2308 int
2197 sysevent_register_event(sysevent_handle_t *shp, 2309 sysevent_register_event(sysevent_handle_t *shp,
2386 SH_ID(shp), 0, NULL); 2498 SH_ID(shp), 0, NULL);
2387 2499
2388 /* Close down event delivery facilities */ 2500 /* Close down event delivery facilities */
2389 (void) door_revoke(SH_DOOR_DESC(shp)); 2501 (void) door_revoke(SH_DOOR_DESC(shp));
2390 (void) fdetach(SH_DOOR_NAME(shp)); 2502 (void) fdetach(SH_DOOR_NAME(shp));
2391
2392 2503
2393 /* 2504 /*
2394 * Release resources and wait for pending event delivery to 2505 * Release resources and wait for pending event delivery to
2395 * complete. 2506 * complete.
2396 */ 2507 */
2397 (void) mutex_lock(&sub_info->sp_qlock); 2508 (void) mutex_lock(&sub_info->sp_qlock);
2398 SH_BOUND(shp) = 0; 2509 SH_BOUND(shp) = 0;
2399 /* Signal event handler and drain the subscriber's event queue */ 2510 /* Signal event handler and drain the subscriber's event queue */
2400 (void) cond_signal(&sub_info->sp_cv); 2511 (void) cond_signal(&sub_info->sp_cv);
2401 (void) mutex_unlock(&sub_info->sp_qlock); 2512 (void) mutex_unlock(&sub_info->sp_qlock);
2402 (void) thr_join(sub_info->sp_handler_tid, NULL, NULL); 2513 if (sub_info->sp_handler_tid != NULL)
2514 (void) thr_join(sub_info->sp_handler_tid, NULL, NULL);
2403 2515
2404 (void) cond_destroy(&sub_info->sp_cv); 2516 (void) cond_destroy(&sub_info->sp_cv);
2405 (void) mutex_destroy(&sub_info->sp_qlock); 2517 (void) mutex_destroy(&sub_info->sp_qlock);
2406 free(sub_info->sp_door_name); 2518 free(sub_info->sp_door_name);
2407 free(sub_info); 2519 free(sub_info);
2445 2557
2446 /* 2558 /*
2447 * Evolving APIs to subscribe to syseventd(1M) system events. 2559 * Evolving APIs to subscribe to syseventd(1M) system events.
2448 */ 2560 */
2449 2561
2450 /* 2562 static sysevent_handle_t *
2451 * sysevent_bind_handle - Bind application event handler for syseventd 2563 sysevent_bind_handle_cmn(void (*event_handler)(sysevent_t *ev),
2452 * subscription. 2564 sysevent_subattr_t *subattr)
2453 */
2454 sysevent_handle_t *
2455 sysevent_bind_handle(void (*event_handler)(sysevent_t *ev))
2456 { 2565 {
2457 sysevent_handle_t *shp; 2566 sysevent_handle_t *shp;
2458 2567
2459 if (getuid() != 0) { 2568 if (getuid() != 0) {
2460 errno = EACCES; 2569 errno = EACCES;
2468 2577
2469 if ((shp = sysevent_open_channel(SYSEVENTD_CHAN)) == NULL) { 2578 if ((shp = sysevent_open_channel(SYSEVENTD_CHAN)) == NULL) {
2470 return (NULL); 2579 return (NULL);
2471 } 2580 }
2472 2581
2473 if (sysevent_bind_subscriber(shp, event_handler) != 0) { 2582 if (sysevent_bind_xsubscriber(shp, event_handler, subattr) != 0) {
2474
2475 /* 2583 /*
2476 * Ask syseventd to clean-up any stale subcribers and try to 2584 * Ask syseventd to clean-up any stale subcribers and try to
2477 * to bind again 2585 * to bind again
2478 */ 2586 */
2479 if (errno == EBUSY) { 2587 if (errno == EBUSY) {
2494 (void) clnt_deliver_event(pub_fd, (void *)&rargs, 2602 (void) clnt_deliver_event(pub_fd, (void *)&rargs,
2495 sizeof (struct reg_args), &result, sizeof (result)); 2603 sizeof (struct reg_args), &result, sizeof (result));
2496 (void) close(pub_fd); 2604 (void) close(pub_fd);
2497 2605
2498 /* Try to bind again */ 2606 /* Try to bind again */
2499 if (sysevent_bind_subscriber(shp, event_handler) != 0) { 2607 if (sysevent_bind_xsubscriber(shp, event_handler,
2608 subattr) != 0) {
2500 sysevent_close_channel(shp); 2609 sysevent_close_channel(shp);
2501 return (NULL); 2610 return (NULL);
2502 } 2611 }
2503 } else { 2612 } else {
2504 sysevent_close_channel(shp); 2613 sysevent_close_channel(shp);
2508 2617
2509 return (shp); 2618 return (shp);
2510 } 2619 }
2511 2620
2512 /* 2621 /*
2622 * sysevent_bind_handle - Bind application event handler for syseventd
2623 * subscription.
2624 */
2625 sysevent_handle_t *
2626 sysevent_bind_handle(void (*event_handler)(sysevent_t *ev))
2627 {
2628 return (sysevent_bind_handle_cmn(event_handler, NULL));
2629 }
2630
2631 /*
2632 * sysevent_bind_xhandle - Bind application event handler for syseventd
2633 * subscription, using door_xcreate and attributes as specified.
2634 */
2635 sysevent_handle_t *
2636 sysevent_bind_xhandle(void (*event_handler)(sysevent_t *ev),
2637 sysevent_subattr_t *subattr)
2638 {
2639 return (sysevent_bind_handle_cmn(event_handler, subattr));
2640 }
2641
2642 /*
2513 * sysevent_unbind_handle - Unbind caller from syseventd subscriptions 2643 * sysevent_unbind_handle - Unbind caller from syseventd subscriptions
2514 */ 2644 */
2515 void 2645 void
2516 sysevent_unbind_handle(sysevent_handle_t *shp) 2646 sysevent_unbind_handle(sysevent_handle_t *shp)
2517 { 2647 {