diff options
| author | Tom Whitten <tom.whitten@oracle.com> | 2010-05-04 08:40:15 -0700 |
|---|---|---|
| committer | Tom Whitten <tom.whitten@oracle.com> | 2010-05-04 08:40:15 -0700 |
| commit | b5cbdab0c8b323a06b6b8ef6a54b56bcc91917c3 (patch) | |
| tree | ed2d6ced7ef59e0a8e5a7ccd545704c53b78c02d /usr/src/cmd/svc | |
| parent | 310da939904e5e37a19c8a427209c0d4d9683ec8 (diff) | |
| download | illumos-joyent-b5cbdab0c8b323a06b6b8ef6a54b56bcc91917c3.tar.gz | |
6531656 svc.configd fails assertion in rc_notify_remove_locked: rc_notify_in_use == 0
Diffstat (limited to 'usr/src/cmd/svc')
| -rw-r--r-- | usr/src/cmd/svc/configd/rc_node.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/usr/src/cmd/svc/configd/rc_node.c b/usr/src/cmd/svc/configd/rc_node.c index a8aa4c32a7..f08f446e76 100644 --- a/usr/src/cmd/svc/configd/rc_node.c +++ b/usr/src/cmd/svc/configd/rc_node.c @@ -590,6 +590,13 @@ static audit_special_prop_item_t special_props_list[] = { * The rc_pg_notify_lock protects all notification state. The rc_pg_notify_cv * is used for global signalling, and each client has a cv which he waits for * events of interest on. + * + * rc_notify_in_use is used to protect rc_notify_list from deletions when + * the rc_pg_notify_lock is dropped. Specifically, rc_notify_info_wait() + * must drop the lock to call rc_node_assign(), and then it reacquires the + * lock. Deletions from rc_notify_list during this period are not + * allowed. Insertions do not matter, because they are always done at the + * end of the list. */ static uu_list_t *rc_notify_info_list; static uu_list_t *rc_notify_list; @@ -7369,6 +7376,14 @@ rc_notify_info_remove_locked(rc_notify_info_t *rnip) * clean up any notifications at the beginning of the list */ if (uu_list_first(rc_notify_list) == me) { + /* + * We can't call rc_notify_remove_locked() unless + * rc_notify_in_use is 0. + */ + while (rc_notify_in_use) { + (void) pthread_cond_wait(&rc_pg_notify_cv, + &rc_pg_notify_lock); + } while ((np = uu_list_next(rc_notify_list, me)) != NULL && np->rcn_info == NULL) rc_notify_remove_locked(np); @@ -7548,8 +7563,20 @@ rc_notify_info_wait(rc_notify_info_t *rnip, rc_node_ptr_t *out, (void) pthread_mutex_lock(&rc_pg_notify_lock); assert(rc_notify_in_use > 0); rc_notify_in_use--; - if (am_first_info) + + if (am_first_info) { + /* + * While we had the lock dropped, another thread + * may have also incremented rc_notify_in_use. We + * need to make sure that we're back to 0 before + * removing the node. + */ + while (rc_notify_in_use) { + (void) pthread_cond_wait(&rc_pg_notify_cv, + &rc_pg_notify_lock); + } rc_notify_remove_locked(np); + } if (rc_notify_in_use == 0) (void) pthread_cond_broadcast(&rc_pg_notify_cv); (void) pthread_mutex_unlock(&rc_pg_notify_lock); |
