diff --git a/locale/findlocale.c b/locale/findlocale.c index 64f687ea9d..fc433b61d8 100644 --- a/locale/findlocale.c +++ b/locale/findlocale.c @@ -348,6 +348,6 @@ _nl_remove_locale (int locale, struct __locale_data *data) } /* This does the real work. */ - _nl_unload_locale (data); + _nl_unload_locale (locale, data); } } diff --git a/locale/loadarchive.c b/locale/loadarchive.c index 5a2356707f..fcc4913319 100644 --- a/locale/loadarchive.c +++ b/locale/loadarchive.c @@ -515,7 +515,7 @@ _nl_archive_subfreeres (void) free (dead->name); for (category = 0; category < __LC_LAST; ++category) if (category != LC_ALL && dead->data[category] != NULL) - _nl_unload_locale (dead->data[category]); + _nl_unload_locale (category, dead->data[category]); free (dead); } archloaded = NULL; diff --git a/locale/loadlocale.c b/locale/loadlocale.c index b8cd1aa441..9069bafcd8 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -101,8 +101,7 @@ _nl_intern_locale_data (int category, const void *data, size_t datasize) newdata->filedata = (void *) filedata; newdata->filesize = datasize; - newdata->private.data = NULL; - newdata->private.cleanup = NULL; + memset (&newdata->private, 0, sizeof (newdata->private)); newdata->usage_count = 0; newdata->use_translit = 0; newdata->nstrings = filedata->nstrings; @@ -282,10 +281,18 @@ _nl_load_locale (struct loaded_l10nfile *file, int category) } void -_nl_unload_locale (struct __locale_data *locale) +_nl_unload_locale (int category, struct __locale_data *locale) { - if (locale->private.cleanup) - (*locale->private.cleanup) (locale); + /* Deallocate locale->private. */ + switch (category) + { + case LC_CTYPE: + _nl_cleanup_ctype (locale); + break; + case LC_TIME: + _nl_cleanup_time (locale); + break; + } switch (__builtin_expect (locale->alloc, ld_mapped)) { diff --git a/locale/localeinfo.h b/locale/localeinfo.h index 87d3b48c16..8ce072b7b4 100644 --- a/locale/localeinfo.h +++ b/locale/localeinfo.h @@ -58,18 +58,13 @@ struct __locale_data ld_archive /* Both point into mmap'd archive regions. */ } alloc; - /* This provides a slot for category-specific code to cache data computed - about this locale. That code can set a cleanup function to deallocate - the data. */ - struct + /* This provides a slot for category-specific code to cache data + computed about this locale. This is deallocated at the start of + _nl_unload_locale. */ + union { - void (*cleanup) (struct __locale_data *); - union - { - void *data; - struct lc_time_data *time; - const struct gconv_fcts *ctype; - }; + struct lc_time_data *time; + const struct gconv_fcts *ctype; } private; unsigned int usage_count; /* Counter for users. */ @@ -349,7 +344,8 @@ extern void _nl_load_locale (struct loaded_l10nfile *file, int category) attribute_hidden; /* Free all resource. */ -extern void _nl_unload_locale (struct __locale_data *locale) attribute_hidden; +extern void _nl_unload_locale (int category, struct __locale_data *locale) + attribute_hidden; /* Free the locale and give back all memory if the usage count is one. */ extern void _nl_remove_locale (int locale, struct __locale_data *data) @@ -409,7 +405,8 @@ extern int _nl_parse_alt_digit (const char **strp, /* Postload processing. */ extern void _nl_postload_ctype (void); -/* Functions used for the `private.cleanup' hook. */ +/* Deallocate category-specific data. Used in _nl_unload_locale. */ +extern void _nl_cleanup_ctype (struct __locale_data *) attribute_hidden; extern void _nl_cleanup_time (struct __locale_data *) attribute_hidden; diff --git a/locale/setlocale.c b/locale/setlocale.c index 38e9bec6bb..56c14d8533 100644 --- a/locale/setlocale.c +++ b/locale/setlocale.c @@ -489,7 +489,7 @@ free_category (int category, struct __locale_data *data = (struct __locale_data *) runp->data; if (data != NULL && data != c_data) - _nl_unload_locale (data); + _nl_unload_locale (category, data); runp = runp->next; free ((char *) curr->filename); free (curr); diff --git a/time/alt_digit.c b/time/alt_digit.c index ae22b3f927..7ed9b6b0a5 100644 --- a/time/alt_digit.c +++ b/time/alt_digit.c @@ -41,7 +41,6 @@ _nl_init_alt_digit (struct __locale_data *current) if (current->private.time == NULL) return; memset (current->private.time, 0, sizeof *current->private.time); - current->private.cleanup = &_nl_cleanup_time; } data = current->private.time; @@ -110,7 +109,6 @@ _nl_get_walt_digit (unsigned int number, struct __locale_data *current) if (current->private.time == NULL) goto out; memset (current->private.time, 0, sizeof *current->private.time); - current->private.cleanup = &_nl_cleanup_time; } data = current->private.time; diff --git a/time/era.c b/time/era.c index 43528ad0d2..d4b538c7b0 100644 --- a/time/era.c +++ b/time/era.c @@ -53,7 +53,6 @@ _nl_init_era_entries (struct __locale_data *current) if (current->private.time == NULL) goto out; memset (current->private.time, 0, sizeof *current->private.time); - current->private.cleanup = &_nl_cleanup_time; } data = current->private.time; diff --git a/time/lc-time-cleanup.c b/time/lc-time-cleanup.c index 2734e25815..f844e04905 100644 --- a/time/lc-time-cleanup.c +++ b/time/lc-time-cleanup.c @@ -26,7 +26,6 @@ _nl_cleanup_time (struct __locale_data *locale) if (data != NULL) { locale->private.time = NULL; - locale->private.cleanup = NULL; free (data->eras); free (data->alt_digits); diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c index ffb5cb7b87..af539a099a 100644 --- a/wcsmbs/wcsmbsload.c +++ b/wcsmbs/wcsmbsload.c @@ -202,10 +202,7 @@ __wcsmbs_load_conv (struct __locale_data *new_category) new_category->private.ctype = &__wcsmbs_gconv_fcts_c; } else - { - new_category->private.ctype = new_fcts; - new_category->private.cleanup = &_nl_cleanup_ctype; - } + new_category->private.ctype = new_fcts; } __libc_rwlock_unlock (__libc_setlocale_lock); @@ -267,10 +264,9 @@ void _nl_cleanup_ctype (struct __locale_data *locale) { const struct gconv_fcts *const data = locale->private.ctype; - if (data != NULL) + if (data != NULL && data != &__wcsmbs_gconv_fcts_c) { locale->private.ctype = NULL; - locale->private.cleanup = NULL; /* Free the old conversions. */ __gconv_close_transform (data->tomb, data->tomb_nsteps);