about summary refs log tree commit diff
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2004-09-26 04:45:24 +0000
committerUlrich Drepper <drepper@redhat.com>2004-09-26 04:45:24 +0000
commitce7265c7438e18f2e4ea81582131a783a1cdd601 (patch)
treede765fda756af9cf90b3d7d3c528ac0c11f93de9 /intl/dcigettext.c
parentf6b90f42997f98bdd91dac713d610b66edc55c7c (diff)
downloadglibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.tar.gz
glibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.tar.xz
glibc-ce7265c7438e18f2e4ea81582131a783a1cdd601.zip
[BZ #322]
Update.
	* intl/dcigettext.c (DCIGETTEXT): Protect tfind/tsearch calls.
	* intl/dcigettext.c (_nl_find_msg): Call _nl_load_domain also if
	decided < 0.
	* intl/finddomain.c (_nl_find_domain): Likewise.
	* intl/l10nflist.c (_nl_make_l10nflist): Initialize lock.
	* intl/loadinfo.h (struct loaded_l10nfile): Add lock element.
	* intl/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.
	duplicate address recognition does not copy junk.  [BZ #322]
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r--intl/dcigettext.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index fa53b7c574..d7111729b9 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -1,5 +1,5 @@
 /* Implementation of the internal dcigettext function.
-   Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -439,7 +439,15 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
   search->domainname = (char *) domainname;
   search->category = category;
 
+  /* 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)
     {
@@ -633,9 +641,14 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
 		      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.  */
@@ -680,7 +693,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
   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)