Mercurial > illumos > illumos-gate
changeset 10854:5d13dd0ac710
6863709 nscd dumps core after receiving SIGHUP
author | Michen Chang <Michen.Chang@Sun.COM> |
---|---|
date | Sat, 24 Oct 2009 07:00:32 -0700 |
parents | 05b7c23148c1 |
children | ff1573ed949f |
files | usr/src/cmd/nscd/nscd_getentctx.c usr/src/cmd/nscd/nscd_init.c usr/src/cmd/nscd/nscd_nswconfig.c usr/src/cmd/nscd/nscd_nswstate.c usr/src/cmd/nscd/nscd_switch.h |
diffstat | 5 files changed, 152 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/nscd/nscd_getentctx.c Sat Oct 24 16:23:18 2009 +0800 +++ b/usr/src/cmd/nscd/nscd_getentctx.c Sat Oct 24 07:00:32 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -160,7 +160,7 @@ /* * If the ctx is not to be deleted and the cookie numbers - * match, return the ctx if not aborted and not in use, + * match, return the ctx if not aborted and not in use. * Otherwise return NULL. */ if (gnctx->to_delete == 0 && gnctx->cookie_num == cookie_num) { @@ -288,6 +288,13 @@ (me, "getent context %p\n", gnctx); _nscd_put_nsw_state(gnctx->nsw_state); + + if (gnctx->base != NULL) { + /* remove reference to the getent context base */ + _nscd_release((nscd_acc_data_t *)gnctx->base); + gnctx->base = NULL; + } + _nscd_del_getent_ctx(gnctx, gnctx->cookie_num); free(gnctx); } @@ -421,11 +428,10 @@ base->num_waiter--; } else { base->first = _nscd_create_getent_ctx(params); - if (base->first != NULL) { - base->first->base = base; + if (base->first != NULL) base->num_getent_ctx++; - } else { - /* not able to create an getent ctx */ + else { + /* not able to create a getent ctx */ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR) @@ -453,6 +459,13 @@ _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) (me, "got a getent ctx %p\n", c); + /* + * reference count the getent context base bfore handing out + * the getent context + */ + c->base = (nscd_getent_ctx_base_t *) + _nscd_get((nscd_acc_data_t *)base); + _nscd_mutex_unlock((nscd_acc_data_t *)base); _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG) @@ -487,7 +500,7 @@ base = gnctx->base; - /* if context base is gone, so should this context */ + /* if context base is gone or no longer current, free this context */ if ((_nscd_mutex_lock((nscd_acc_data_t *)base)) == NULL) { _nscd_free_getent_ctx(gnctx); return; @@ -533,6 +546,10 @@ gnctx->n_src = 0; gnctx->be = NULL; + /* remove reference to the getent context base */ + _nscd_release((nscd_acc_data_t *)base); + gnctx->base = NULL; + _nscd_mutex_unlock((nscd_acc_data_t *)base); }
--- a/usr/src/cmd/nscd/nscd_init.c Sat Oct 24 16:23:18 2009 +0800 +++ b/usr/src/cmd/nscd/nscd_init.c Sat Oct 24 07:00:32 2009 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <locale.h> #include <unistd.h> #include <string.h> @@ -204,17 +202,6 @@ char errmsg[1024]; /* - * re-read the nsswitch configuration - */ - rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err); - if (rc != NSCD_SUCCESS) { - (void) snprintf(errmsg, sizeof (errmsg), - "unable to parse the config file %s (rc = %d), %s\n", - "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err)); - goto error_exit; - } - - /* * re-read the nscd configuration */ if (cfgfile_save == NULL) @@ -241,7 +228,7 @@ } _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ALL) - (me, "nsswitch/nscd configuration refreshed successfully\n"); + (me, "nscd configuration refreshed successfully\n"); return (NSCD_SUCCESS);
--- a/usr/src/cmd/nscd/nscd_nswconfig.c Sat Oct 24 16:23:18 2009 +0800 +++ b/usr/src/cmd/nscd/nscd_nswconfig.c Sat Oct 24 07:00:32 2009 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <nss_common.h> #include <dlfcn.h> #include <alloca.h> @@ -210,7 +208,8 @@ for (i = 0; i < NSCD_NUM_DB; i++) { - if (nscd_nsw_config[i] == NULL) + /* no nsswitch configuration, no backend info db population */ + if (nscd_nsw_config[i] == NULL || *nscd_nsw_config[i] == NULL) continue; nsw_cfg = *nscd_nsw_config[i]; @@ -465,15 +464,6 @@ (void) (nscd_nss_db_initf[dbi])(&nsw_cfg->fe_params); /* - * activate the new nscd_nsw_config_t, the old one - * will either be deleted or left on the side (and be - * deleted eventually) - */ - nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( - (nscd_acc_data_t *)nscd_nsw_config[dbi], - (nscd_acc_data_t *)nsw_cfg_p); - - /* * also create a new nsw state base */ if ((rc = _nscd_init_nsw_state_base(dbi, compat_basei, 1)) != @@ -504,6 +494,17 @@ (me, "new nsw config created (database = %s, " "config = %s)\n", dbn, cfgstr); + /* + * Activate the new nscd_nsw_config_t and make it the + * current nsswitch config. The old one pointed to by + * nscd_nsw_config[dbi] will either be destroyed + * immediately or left on the side line (and be + * destroyed eventually). __nscd_set() will set the + * associated flags to make it happen. + */ + nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( + (nscd_acc_data_t *)nscd_nsw_config[dbi], + (nscd_acc_data_t *)nsw_cfg_p); error_exit: @@ -537,11 +538,40 @@ char *me = "create_nsw_config"; /* - * if pseudo-databases (initf function not defined), - * don't bother now + * Allocate a pointer space for saving a pointer to a + * nscd_nsw_config_t. _nscd_alloc() will also create + * a nscd_access_t header with a rwlock_t and mutex_t + * for controlling later access to the data pointed + * to by the pointer. */ - if (nscd_nss_db_initf[dbi] == NULL) + nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, + sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, + NSCD_ALLOC_RWLOCK | NSCD_ALLOC_MUTEX); + + if (nsw_cfg_p == NULL) { + _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) + (me, "unable to allocate a space for a nsw config pointer\n"); + return (NSCD_NO_MEMORY); + } + _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) + (me, "addr for saving nsw config pointer = %p\n", nsw_cfg_p); + + /* + * If pseudo-databases (initf function not defined), + * no need to create a nscd_nsw_config_t yet, + * so put a NULL pointer in the pointer space. + */ + if (nscd_nss_db_initf[dbi] == NULL) { + *nsw_cfg_p = NULL; + nscd_nsw_config[dbi] = (nscd_nsw_config_t **)_nscd_set( + (nscd_acc_data_t *)nscd_nsw_config[dbi], + (nscd_acc_data_t *)nsw_cfg_p); + + _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) + (me, "pointer to nsw config has been set to NULL\n"); + return (NSCD_SUCCESS); + } /* allocate the space for a nscd_nsw_config_t */ nsw_cfg = calloc(1, sizeof (nscd_nsw_config_t)); @@ -553,18 +583,6 @@ _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "nsw config structure %pallocated\n", nsw_cfg); - nsw_cfg_p = (nscd_nsw_config_t **)_nscd_alloc(NSCD_DATA_NSW_CONFIG, - sizeof (nscd_nsw_config_t **), free_nscd_nsw_config, - NSCD_ALLOC_RWLOCK); - - if (nsw_cfg_p == NULL) { - _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) - (me, "unable to allocate a pointer to nsw config structure\n"); - return (NSCD_NO_MEMORY); - } - _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) - (me, "nsw config pointer = %p\n", nsw_cfg_p); - nsw_cfg->db_name = strdup(NSCD_NSW_DB_NAME(dbi)); if (nsw_cfg->db_name == NULL) { _NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
--- a/usr/src/cmd/nscd/nscd_nswstate.c Sat Oct 24 16:23:18 2009 +0800 +++ b/usr/src/cmd/nscd/nscd_nswstate.c Sat Oct 24 07:00:32 2009 -0700 @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <stdlib.h> #include <assert.h> @@ -95,7 +93,11 @@ if (s->be_version_p != NULL) free(s->be_version_p); - s->base = NULL; + /* remove reference to the nsw state base */ + if (s->base != NULL) { + _nscd_release((nscd_acc_data_t *)s->base); + s->base = NULL; + } _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state %p freed \n", s); @@ -425,43 +427,74 @@ */ if (params->compati != -1) { - nscd_nsw_config_t **nswcfg1; + nscd_nsw_config_t **nswcfg1, **nswcfg2; int i = params->compati; dbi = i; + /* + * retrieve the pointer space which contains a + * pointer pointing to the nsswitch config + * structure for the compat backend + */ nswcfg = (nscd_nsw_config_t **)_nscd_get( (nscd_acc_data_t *)nscd_nsw_config[i]); /* - * if nsw data structures not created yet, get the - * config string from the passwd_compat or - * group_compat DB and create the structures + * If nsswitch config structure not created yet, + * get the config string from the passwd_compat + * or group_compat DB and create the structure. */ - if (nswcfg == NULL) { - nswcfg1 = (nscd_nsw_config_t **)_nscd_get( - (nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]); - if (nswcfg1 == NULL) { - _NSCD_LOG(NSCD_LOG_NSW_STATE, - NSCD_LOG_LEVEL_ERROR) - (me, "no nsw config for %s\n", - params->p.name); - return (NSCD_CREATE_NSW_STATE_FAILED); + if (*nswcfg == NULL) { + /* Wait first if it's being created. */ + nswcfg2 = (nscd_nsw_config_t **)_nscd_mutex_lock( + (nscd_acc_data_t *)nscd_nsw_config[i]); + + /* still not created yet */ + if (*nswcfg2 == NULL) { + /* + * get the nsswitch config string specified + * for passwd_compat or group_compat + */ + nswcfg1 = (nscd_nsw_config_t **)_nscd_get( + (nscd_acc_data_t *) + nscd_nsw_config[params->cfgdbi]); + if (nswcfg1 == NULL) { + _NSCD_LOG(NSCD_LOG_NSW_STATE, + NSCD_LOG_LEVEL_ERROR) + (me, "no nsw config for %s\n", + params->p.name); + + (void) _nscd_mutex_unlock( + (nscd_acc_data_t *)nswcfg2); + _nscd_release((nscd_acc_data_t *) + nswcfg); + + return (NSCD_CREATE_NSW_STATE_FAILED); + } + + rc = _nscd_create_sw_struct(i, params->cfgdbi, + params->p.name, (*nswcfg1)->nsw_cfg_str, + NULL, params); + _nscd_release((nscd_acc_data_t *)nswcfg1); + + if (rc == NSCD_SUCCESS) { + _NSCD_LOG(NSCD_LOG_NSW_STATE, + NSCD_LOG_LEVEL_DEBUG) + (me, "nsw config created for %s (%s)\n", + params->p.name, + (*nswcfg1)->nsw_cfg_str); + } else { + (void) _nscd_mutex_unlock( + (nscd_acc_data_t *)nswcfg2); + _nscd_release((nscd_acc_data_t *) + nswcfg); + return (rc); + } } - - rc = _nscd_create_sw_struct(i, params->cfgdbi, - params->p.name, (*nswcfg1)->nsw_cfg_str, - NULL, params); - _nscd_release((nscd_acc_data_t *)nswcfg1); - if (rc != NSCD_SUCCESS) - return (rc); - - _NSCD_LOG(NSCD_LOG_NSW_STATE, - NSCD_LOG_LEVEL_DEBUG) - (me, "nsw config created for %s (%s)\n", - params->p.name, (*nswcfg1)->nsw_cfg_str); - } else - _nscd_release((nscd_acc_data_t *)nswcfg); + (void) _nscd_mutex_unlock((nscd_acc_data_t *)nswcfg2); + } + _nscd_release((nscd_acc_data_t *)nswcfg); } (void) rw_rdlock(&nscd_nsw_state_base_lock); @@ -573,8 +606,6 @@ ctrl_p->first = _nscd_create_nsw_state(params); if (ctrl_p->first != NULL) { - ctrl_p->first->base = base; - if (tid == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) @@ -624,6 +655,13 @@ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "got old nsw state %p\n", ret); + /* + * reference count the nsswitch state base bfore handing out + * the nsswitch state + */ + ret->base = (nscd_nsw_state_base_t *) + _nscd_get((nscd_acc_data_t *)base); + _nscd_mutex_unlock((nscd_acc_data_t *)base); rootp->s = (struct nss_db_state *)ret; @@ -687,9 +725,9 @@ base = s->base; if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) { - /* base has been freed, free this db state */ + /* base has been freed or no longer valid, free the nsw state */ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) - (me, "nsw state base has been freed, freeing %p\n", s); + (me, "nsw state base gone or no longer valid, freeing %p\n", s); _nscd_free_nsw_state(s); return; } @@ -721,6 +759,12 @@ } ctrl_p->free++; + /* + * Remove reference to the nsswitch state base. + */ + _nscd_release((nscd_acc_data_t *)base); + s->base = NULL; + _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "signaling waiter thread_only = %d..\n", thread_only);
--- a/usr/src/cmd/nscd/nscd_switch.h Sat Oct 24 16:23:18 2009 +0800 +++ b/usr/src/cmd/nscd/nscd_switch.h Sat Oct 24 07:00:32 2009 -0700 @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -125,8 +125,6 @@ */ typedef struct nscd_getent_ctx_base { int dbi; /* which database? */ - int deattached; /* not associated with */ - /* current config */ int max_getent_ctx; int num_getent_ctx; int num_waiter;