summaryrefslogtreecommitdiff
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-03-30 23:40:18 +0000
committerUlrich Drepper <drepper@redhat.com>2008-03-30 23:40:18 +0000
commit2ecc7d93b88b5b9e8ef5833c541d2db1c4608799 (patch)
treef404523e0a8d3fc70746d2a38cb31574fd1f30aa /intl/dcigettext.c
parentfaa091c673792ef8d148e1d2117c853da8a961a8 (diff)
downloadglibc-2ecc7d93b88b5b9e8ef5833c541d2db1c4608799.tar.gz
* 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.c30
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);