diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-03-30 23:40:18 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2008-03-30 23:40:18 +0000 |
commit | 2ecc7d93b88b5b9e8ef5833c541d2db1c4608799 (patch) | |
tree | f404523e0a8d3fc70746d2a38cb31574fd1f30aa /intl/dcigettext.c | |
parent | faa091c673792ef8d148e1d2117c853da8a961a8 (diff) | |
download | glibc-2ecc7d93b88b5b9e8ef5833c541d2db1c4608799.tar.gz glibc-2ecc7d93b88b5b9e8ef5833c541d2db1c4608799.tar.xz glibc-2ecc7d93b88b5b9e8ef5833c541d2db1c4608799.zip |
* intl/dcigettext.c (_nl_find_msg): Reread nconversions after
acquiring wrlock. Do conv_tab allocation while holding lock. * intl/Makefile: Add rules to build and run tst-gettext6. * intl/tst-gettext6.c: New test. * intl/tst-gettext6.sh: New file.
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r-- | intl/dcigettext.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 7004cd49cf..f8a0311f68 100644 --- a/intl/dcigettext.c +++ b/intl/dcigettext.c @@ -879,6 +879,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) { /* We have to allocate a new conversions table. */ __libc_rwlock_wrlock (domain->conversions_lock); + nconversions = domain->nconversions; /* Maybe in the meantime somebody added the translation. Recheck. */ @@ -1033,6 +1034,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) # endif ) { + __libc_lock_define_initialized (static, lock) /* We are supposed to do a conversion. First allocate an appropriate table with the same structure as the table of translations in the file, where we can put the pointers @@ -1042,13 +1044,21 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) handle this case by converting RESULTLEN bytes, including NULs. */ - if (convd->conv_tab == NULL - && ((convd->conv_tab = - (char **) calloc (nstrings + domain->n_sysdep_strings, - sizeof (char *))) - == NULL)) - /* Mark that we didn't succeed allocating a table. */ - convd->conv_tab = (char **) -1; + if (__builtin_expect (convd->conv_tab == NULL, 0)) + { + __libc_lock_lock (lock); + if (convd->conv_tab == NULL) + { + convd->conv_tab + = calloc (nstrings + domain->n_sysdep_strings, + sizeof (char *)); + if (convd->conv_tab != NULL) + goto not_translated_yet; + /* Mark that we didn't succeed allocating a table. */ + convd->conv_tab = (char **) -1; + } + __libc_lock_unlock (lock); + } if (__builtin_expect (convd->conv_tab == (char **) -1, 0)) /* Nothing we can do, no more memory. We cannot use the @@ -1057,12 +1067,14 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) if (convd->conv_tab[act] == NULL) { + __libc_lock_lock (lock); + not_translated_yet:; + /* We haven't used this string so far, so it is not translated yet. Do this now. */ /* We use a bit more efficient memory handling. We allocate always larger blocks which get used over time. This is faster than many small allocations. */ - __libc_lock_define_initialized (static, lock) # define INITIAL_BLOCK_SIZE 4080 static unsigned char *freemem; static size_t freemem_size; @@ -1074,8 +1086,6 @@ _nl_find_msg (domain_file, domainbinding, msgid, convert, lengthp) transmem_block_t *transmem_list = NULL; # endif - __libc_lock_lock (lock); - inbuf = (const unsigned char *) result; outbuf = freemem + sizeof (size_t); |