Mercurial > illumos > illumos-gate
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 { |