]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
glibc 2004-09-25 Ulrich Drepper <drepper@redhat.com>
authorBruno Haible <bruno@clisp.org>
Tue, 24 May 2005 10:38:20 +0000 (10:38 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:12:36 +0000 (12:12 +0200)
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/dcigettext.c
gettext-runtime/intl/finddomain.c
gettext-runtime/intl/loadmsgcat.c

index 26016fc12e4528935be9dbc9633f72065fe8d5df..0e4474a971c8b5977a305b7fdcf5239c5579fa1c 100644 (file)
@@ -1,3 +1,26 @@
+2005-05-05  Bruno Haible  <bruno@clisp.org>
+
+       * dcigettext.c (__libc_rwlock_wrlock): Define fallback.
+       * finddomain.c (__libc_rwlock_define_initialized,
+       __libc_rwlock_rdlock, __libc_rwlock_wrlock, __libc_rwlock_unlock):
+       Define fallbacks.
+       * loadmsgcat.c (__libc_lock_define_initialized_recursive,
+       __libc_lock_lock_recursive, __libc_lock_unlock_recursive): Define
+       fallbacks.
+       (_nl_load_domain): Fix portability problems in last patch.
+       
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+       * dcigettext.c (DCIGETTEXT): Protect tfind/tsearch calls.
+       * dcigettext.c (_nl_find_msg): Call _nl_load_domain also if
+       decided < 0.
+       * finddomain.c (_nl_find_domain): Likewise.
+       * loadmsgcat.c (_nl_load_domain): Set decided to 1 only once we
+       are done.  First set to -1 to signal initialization is ongoing.
+       Protect against concurrent callers with recursive lock.
+       * finddomain.c (_nl_find_domain): Protect calls to
+       _nl_make_l10nflist.  [BZ #322]
+
 2004-08-06  Jakub Jelinek  <jakub@redhat.com>
 
        * finddomain.c (free_mem): Rename to...
index 4d01774a12b2bb5f1d3488cd66ec9813e4e729f3..738b12b5f54c56b766db42e72215643373401033 100644 (file)
@@ -110,6 +110,7 @@ extern int errno;
 # define __libc_lock_unlock(NAME)
 # define __libc_rwlock_define_initialized(CLASS, NAME)
 # define __libc_rwlock_rdlock(NAME)
+# define __libc_rwlock_wrlock(NAME)
 # define __libc_rwlock_unlock(NAME)
 #endif
 
@@ -534,7 +535,15 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
   search->localename = localename;
 # endif
 
+  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+     tsearch calls can be fatal.  */
+  __libc_rwlock_define_initialized (static, tree_lock);
+  __libc_rwlock_rdlock (tree_lock);
+
   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+
+  __libc_rwlock_unlock (tree_lock);
+
   freea (search);
   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
     {
@@ -727,9 +736,14 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
                      newp->translation = retval;
                      newp->translation_length = retlen;
 
+                     __libc_rwlock_wrlock (tree_lock);
+
                      /* Insert the entry in the search tree.  */
                      foundp = (struct known_translation_t **)
                        tsearch (newp, &root, transcmp);
+
+                     __libc_rwlock_unlock (tree_lock);
+
                      if (foundp == NULL
                          || __builtin_expect (*foundp != newp, 0))
                        /* The insert failed.  */
@@ -794,7 +808,7 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
   char *result;
   size_t resultlen;
 
-  if (domain_file->decided == 0)
+  if (domain_file->decided <= 0)
     _nl_load_domain (domain_file, domainbinding);
 
   if (domain_file->data == NULL)
index ebc507d6964d147313b147ce59871684f4166742..8523ea8bf4761349d9a1255df4b02ccd1eff45e9 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle list of needed message catalogs
-   Copyright (C) 1995-1999, 2000-2001, 2003-2004 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000-2001, 2003-2005 Free Software Foundation, Inc.
    Written by Ulrich Drepper <drepper@gnu.org>, 1995.
 
    This program is free software; you can redistribute it and/or modify it
 # include "libgnuintl.h"
 #endif
 
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+# define __libc_rwlock_define_initialized(CLASS, NAME)
+# define __libc_rwlock_rdlock(NAME)
+# define __libc_rwlock_wrlock(NAME)
+# define __libc_rwlock_unlock(NAME)
+#endif
+
 /* @@ end of prolog @@ */
 /* List of already loaded domains.  */
 static struct loaded_l10nfile *_nl_loaded_domains;
@@ -83,17 +92,24 @@ _nl_find_domain (const char *dirname, char *locale,
                (7) audience/modifier
    */
 
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_define_initialized (static, lock);
+  __libc_rwlock_rdlock (lock);
+
   /* If we have already tested for this locale entry there has to
      be one data set in the list of loaded domains.  */
   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                               strlen (dirname) + 1, 0, locale, NULL, NULL,
                               NULL, NULL, NULL, NULL, NULL, domainname, 0);
+
+  __libc_rwlock_unlock (lock);
+
   if (retval != NULL)
     {
       /* We know something about this locale.  */
       int cnt;
 
-      if (retval->decided == 0)
+      if (retval->decided <= 0)
        _nl_load_domain (retval, domainbinding);
 
       if (retval->data != NULL)
@@ -101,12 +117,13 @@ _nl_find_domain (const char *dirname, char *locale,
 
       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
        {
-         if (retval->successor[cnt]->decided == 0)
+         if (retval->successor[cnt]->decided <= 0)
            _nl_load_domain (retval->successor[cnt], domainbinding);
 
          if (retval->successor[cnt]->data != NULL)
            break;
        }
+
       return cnt >= 0 ? retval : NULL;
       /* NOTREACHED */
     }
@@ -138,24 +155,30 @@ _nl_find_domain (const char *dirname, char *locale,
                           &codeset, &normalized_codeset, &special,
                           &sponsor, &revision);
 
+  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
+  __libc_rwlock_wrlock (lock);
+
   /* Create all possible locale entries which might be interested in
      generalization.  */
   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                               strlen (dirname) + 1, mask, language, territory,
                               codeset, normalized_codeset, modifier, special,
                               sponsor, revision, domainname, 1);
+
+  __libc_rwlock_unlock (lock);
+
   if (retval == NULL)
     /* This means we are out of core.  */
     return NULL;
 
-  if (retval->decided == 0)
+  if (retval->decided <= 0)
     _nl_load_domain (retval, domainbinding);
   if (retval->data == NULL)
     {
       int cnt;
       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
        {
-         if (retval->successor[cnt]->decided == 0)
+         if (retval->successor[cnt]->decided <= 0)
            _nl_load_domain (retval->successor[cnt], domainbinding);
          if (retval->successor[cnt]->data != NULL)
            break;
index a2d27992874ab0ec68675a82cf927f920cf099f0..26d0b87b15d92e159e1258cedfe351ff145415e3 100644 (file)
@@ -92,6 +92,11 @@ char *alloca ();
 #ifdef _LIBC
 # include "../locale/localeinfo.h"
 # include <not-cancel.h>
+# include <bits/libc-lock.h>
+#else
+# define __libc_lock_define_initialized_recursive(CLASS, NAME)
+# define __libc_lock_lock_recursive(NAME)
+# define __libc_lock_unlock_recursive(NAME)
 #endif
 
 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
@@ -773,7 +778,8 @@ internal_function
 _nl_load_domain (struct loaded_l10nfile *domain_file,
                 struct binding *domainbinding)
 {
-  int fd;
+  __libc_lock_define_initialized_recursive (static, lock);
+  int fd = -1;
   size_t size;
 #ifdef _LIBC
   struct stat64 st;
@@ -787,7 +793,22 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
   const char *nullentry;
   size_t nullentrylen;
 
-  domain_file->decided = 1;
+  __libc_lock_lock_recursive (lock);
+  if (domain_file->decided != 0)
+    {
+      /* There are two possibilities:
+
+        + this is the same thread calling again during this initialization
+          via _nl_find_msg.  We have initialized everything this call needs.
+
+        + this is another thread which tried to initialize this object.
+          Not necessary anymore since if the lock is available this
+          is finished.
+      */
+      goto done;
+    }
+
+  domain_file->decided = -1;
   domain_file->data = NULL;
 
   /* Note that it would be useless to store domainbinding in domain_file
@@ -799,12 +820,12 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
      specification the locale file name is different for XPG and CEN
      syntax.  */
   if (domain_file->filename == NULL)
-    return;
+    goto out;
 
   /* Try to open the addressed file.  */
   fd = open (domain_file->filename, O_RDONLY | O_BINARY);
   if (fd == -1)
-    return;
+    goto out;
 
   /* We must know about the size of the file.  */
   if (
@@ -815,11 +836,8 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
 #endif
       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
-    {
-      /* Something went wrong.  */
-      close (fd);
-      return;
-    }
+    /* Something went wrong.  */
+    goto out;
 
 #ifdef HAVE_MMAP
   /* Now we are ready to load the file.  If mmap() is available we try
@@ -831,6 +849,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
     {
       /* mmap() call was successful.  */
       close (fd);
+      fd = -1;
       use_mmap = 1;
     }
 #endif
@@ -844,7 +863,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
 
       data = (struct mo_file_header *) malloc (size);
       if (data == NULL)
-       return;
+       goto out;
 
       to_read = size;
       read_ptr = (char *) data;
@@ -857,8 +876,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
              if (nb == -1 && errno == EINTR)
                continue;
 #endif
-             close (fd);
-             return;
+             goto out;
            }
          read_ptr += nb;
          to_read -= nb;
@@ -866,6 +884,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
       while (to_read > 0);
 
       close (fd);
+      fd = -1;
     }
 
   /* Using the magic number we can test whether it really is a message
@@ -880,12 +899,12 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
       else
 #endif
        free (data);
-      return;
+      goto out;
     }
 
   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
   if (domain == NULL)
-    return;
+    goto out;
   domain_file->data = domain;
 
   domain->data = (char *) data;
@@ -1247,7 +1266,7 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
        free (data);
       free (domain);
       domain_file->data = NULL;
-      return;
+      goto out;
     }
 
   /* No caches of converted translations so far.  */
@@ -1257,6 +1276,15 @@ _nl_load_domain (struct loaded_l10nfile *domain_file,
   /* Get the header entry and look for a plural specification.  */
   nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+
+ out:
+  if (fd != -1)
+    close (fd);
+
+  domain_file->decided = 1;
+
+ done:
+  __libc_lock_unlock_recursive (lock);
 }