aboutsummaryrefslogtreecommitdiff
path: root/intl/loadmsgcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/loadmsgcat.c')
-rw-r--r--intl/loadmsgcat.c67
1 files changed, 43 insertions, 24 deletions
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 569ace2105..ec886d9bd7 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -899,7 +899,7 @@ _nl_load_domain (domain_file, domainbinding)
struct loaded_l10nfile *domain_file;
struct binding *domainbinding;
{
- int fd;
+ int fd = -1;
size_t size;
#ifdef _LIBC
struct stat64 st;
@@ -912,7 +912,24 @@ _nl_load_domain (domain_file, domainbinding)
int revision;
const char *nullentry;
- domain_file->decided = 1;
+ __libc_lock_lock_recursive (domain_file->lock);
+ if (domain_file->decided != 0)
+ {
+ /* There are two possibilities:
+
+ + is is the same thread calling again during this
+ initialization via _nl_init_domain_conv and _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.
+ */
+ __libc_lock_unlock_recursive (domain_file->lock);
+ return;
+ }
+
+ domain_file->decided = -1;
domain_file->data = NULL;
/* Note that it would be useless to store domainbinding in domain_file
@@ -924,12 +941,12 @@ _nl_load_domain (domain_file, domainbinding)
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);
if (fd == -1)
- return;
+ goto out;
/* We must know about the size of the file. */
if (
@@ -940,11 +957,8 @@ _nl_load_domain (domain_file, domainbinding)
#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
@@ -952,45 +966,42 @@ _nl_load_domain (domain_file, domainbinding)
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
MAP_PRIVATE, fd, 0);
- if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
+ if (__builtin_expect (data != MAP_FAILED, 1))
{
/* mmap() call was successful. */
close (fd);
+ fd = -1;
use_mmap = 1;
}
#endif
/* If the data is not yet available (i.e. mmap'ed) we try to load
it manually. */
- if (data == (struct mo_file_header *) -1)
+ if (data == MAP_FAILED)
{
size_t to_read;
char *read_ptr;
data = (struct mo_file_header *) malloc (size);
if (data == NULL)
- return;
+ goto out;
to_read = size;
read_ptr = (char *) data;
do
{
- long int nb = (long int) read (fd, read_ptr, to_read);
+ long int nb = (long int) TEMP_FAILURE_RETRY (read (fd, read_ptr,
+ to_read));
if (nb <= 0)
- {
-#ifdef EINTR
- if (nb == -1 && errno == EINTR)
- continue;
-#endif
- close (fd);
- return;
- }
+ goto out;
+
read_ptr += nb;
to_read -= nb;
}
while (to_read > 0);
close (fd);
+ fd = -1;
}
/* Using the magic number we can test whether it really is a message
@@ -1005,12 +1016,12 @@ _nl_load_domain (domain_file, domainbinding)
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;
@@ -1372,7 +1383,7 @@ _nl_load_domain (domain_file, domainbinding)
free (data);
free (domain);
domain_file->data = NULL;
- return;
+ goto out;
}
/* Now initialize the character set converter from the character set
@@ -1382,6 +1393,14 @@ _nl_load_domain (domain_file, domainbinding)
/* Also look for a plural specification. */
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+
+ out:
+ if (fd != -1)
+ close (fd);
+
+ domain_file->decided = 1;
+
+ __libc_lock_unlock_recursive (domain_file->lock);
}