- Allow applications to use pthread_atfork without explicitly
  requiring libpthread.so. (#1013801)
- Support `--list-archive FILE' in localedef utility.
This commit is contained in:
Carlos O'Donell 2013-10-03 05:22:51 -04:00
parent 13a25e85c0
commit c2021d0b30
4 changed files with 259 additions and 7 deletions

View File

@ -102,7 +102,7 @@ open_tmpl_archive (struct locarhandle *ah)
struct stat64 st;
int fd;
struct locarhead head;
const char *archivefname = tmpl_file;
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
/* Open the archive. We must have exclusive write access. */
fd = open64 (archivefname, O_RDONLY);
@ -256,7 +256,8 @@ compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
}
static int
fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[],
fill_archive (struct locarhandle *tmpl_ah,
const char *fname, size_t nlist, char *list[],
const char *primary)
{
struct locarhandle ah;
@ -310,6 +311,8 @@ fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[],
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
if (fname != NULL)
ah.fname = fname;
open_archive (&ah, false);
if (primary != NULL)
@ -538,7 +541,7 @@ fill_archive (struct locarhandle *tmpl_ah, size_t nlist, char *list[],
return result;
}
int main ()
int main (int argc, char *argv[])
{
char path[4096];
DIR *dirp;
@ -553,6 +556,10 @@ int main ()
if (dirp == NULL)
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
/* Use the template file as specified on the command line. */
if (argc > 1)
tmpl_ah.fname = argv[1];
open_tmpl_archive (&tmpl_ah);
unlink (locar_file);
@ -629,10 +636,12 @@ int main ()
cnt++;
}
closedir (dirp);
fill_archive (&tmpl_ah, cnt, list, primary);
/* Store the archive to the file specified as the second argument on the
command line or the default locale archive. */
fill_archive (&tmpl_ah, argc > 2 ? argv[2] : NULL, cnt, list, primary);
close_archive (&tmpl_ah);
truncate (tmpl_file, 0);
char *argv[] = { "/usr/sbin/tzdata-update", NULL };
execve (argv[0], (char *const *)argv, (char *const *)&argv[1]);
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
exit (0);
}

140
glibc-localedef-arg.patch Normal file
View File

@ -0,0 +1,140 @@
#
# Posted upstream:
# https://sourceware.org/ml/libc-alpha/2013-10/msg00103.html
#
diff --git a/locale/locarchive.h b/locale/locarchive.h
index f2d8477..fec3b1a 100644
--- a/locale/locarchive.h
+++ b/locale/locarchive.h
@@ -80,6 +80,8 @@ struct locrecent
struct locarhandle
{
+ /* Full path to the locale archive file. */
+ const char *fname;
int fd;
void *addr;
size_t mmaped;
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
index 8b9866a..d664232 100644
--- a/locale/programs/localedef.c
+++ b/locale/programs/localedef.c
@@ -209,7 +209,7 @@ main (int argc, char *argv[])
/* Handle a few special cases. */
if (list_archive)
- show_archive_content (verbose);
+ show_archive_content (remaining > 1 ? argv[remaining] : NULL, verbose);
if (add_to_archive)
return add_locales_to_archive (argc - remaining, &argv[remaining],
replace_archive);
diff --git a/locale/programs/localedef.h b/locale/programs/localedef.h
index e010c72..0cfc416 100644
--- a/locale/programs/localedef.h
+++ b/locale/programs/localedef.h
@@ -170,7 +170,8 @@ extern int add_locales_to_archive (size_t nlist, char *list[], bool replace);
/* Removed named locales from archive. */
extern int delete_locales_from_archive (size_t nlist, char *list[]);
-/* List content of locale archive. */
-extern void show_archive_content (int verbose) __attribute__ ((noreturn));
+/* List content of locale archive. If FNAME is non-null use that as
+ the locale archive to list, otherwise the default. */
+extern void show_archive_content (char *fname, int verbose) __attribute__ ((noreturn));
#endif /* localedef.h */
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
index 13dba0f..b88f1b1 100644
--- a/locale/programs/locarchive.c
+++ b/locale/programs/locarchive.c
@@ -223,6 +223,7 @@ create_archive (const char *archivefname, struct locarhandle *ah)
_("cannot change mode of new locale archive"));
}
+ ah->fname = NULL;
ah->fd = fd;
ah->mmap_base = mmap_base;
ah->mmap_len = mmap_len;
@@ -562,11 +563,19 @@ open_archive (struct locarhandle *ah, bool readonly)
struct locarhead head;
int retry = 0;
size_t prefix_len = output_prefix ? strlen (output_prefix) : 0;
- char archivefname[prefix_len + sizeof (ARCHIVE_NAME)];
+ char fname[prefix_len + sizeof (ARCHIVE_NAME)];
+ char *archivefname = ah->fname;
+ bool defaultfname = false;
- if (output_prefix)
- memcpy (archivefname, output_prefix, prefix_len);
- strcpy (archivefname + prefix_len, ARCHIVE_NAME);
+ /* If ah has a non-NULL fname open that otherwise open the default. */
+ if (archivefname == NULL)
+ {
+ defaultfname = true;
+ archivefname = fname;
+ if (output_prefix)
+ memcpy (archivefname, output_prefix, prefix_len);
+ strcpy (archivefname + prefix_len, ARCHIVE_NAME);
+ }
while (1)
{
@@ -574,8 +583,11 @@ open_archive (struct locarhandle *ah, bool readonly)
fd = open64 (archivefname, readonly ? O_RDONLY : O_RDWR);
if (fd == -1)
{
- /* Maybe the file does not yet exist. */
- if (errno == ENOENT)
+ /* Maybe the file does not yet exist? If we are opening
+ the default locale archive we ignore the failure and
+ list an empty archive, otherwise we print an error
+ and exit. */
+ if (errno == ENOENT && defaultfname)
{
if (readonly)
{
@@ -1324,6 +1336,7 @@ add_locales_to_archive (nlist, list, replace)
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
+ ah.fname = NULL;
open_archive (&ah, false);
while (nlist-- > 0)
@@ -1523,6 +1536,7 @@ delete_locales_from_archive (nlist, list)
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
+ ah.fname = NULL;
open_archive (&ah, false);
head = ah.addr;
@@ -1612,7 +1626,7 @@ dataentcmp (const void *a, const void *b)
void
-show_archive_content (int verbose)
+show_archive_content (char *fname, int verbose)
{
struct locarhandle ah;
struct locarhead *head;
@@ -1622,6 +1636,7 @@ show_archive_content (int verbose)
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
+ ah.fname = fname;
open_archive (&ah, true);
head = ah.addr;
diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
index 4969391..6410cbd 100644
--- a/locale/programs/locfile.c
+++ b/locale/programs/locfile.c
@@ -343,6 +343,7 @@ write_all_categories (struct localedef_t *definitions,
/* Open the archive. This call never returns if we cannot
successfully open the archive. */
+ ah.fname = NULL;
open_archive (&ah, false);
if (add_locale_to_archive (&ah, locname, to_archive, true) != 0)

90
glibc-rh1013801.patch Normal file
View File

@ -0,0 +1,90 @@
#
# Posted upstream:
# https://sourceware.org/ml/libc-alpha/2013-10/msg00065.html
#
# This is related to bug 1013801 in that it fixes the problem
# by modifying the runtime. In bug 1013801 we have libselinux
# using pthread_atfork which pulls in libpthread, but we don't
# want that, we want libpthread to be pulled in only when
# actually needed by the application. This patch makes it
# possible to avoid requiring libpthread and still use
# pthread_atfork.
#
# The general idea for the design is in the leading comment
# in the source code.
#
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
index 6078e2d..36fd50b 100644
--- a/nptl/sysdeps/unix/sysv/linux/Makefile
+++ b/nptl/sysdeps/unix/sysv/linux/Makefile
@@ -18,7 +18,9 @@
ifeq ($(subdir),nptl)
sysdep_routines += register-atfork unregister-atfork libc_pthread_init \
- libc_multiple_threads
+ libc_multiple_threads libc_pthread_atfork
+
+static-only-routines += libc_pthread_atfork
libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock
diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_atfork.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_atfork.c
new file mode 100644
index 0000000..667049a
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_atfork.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* The standard design pattern for making it optional to link against
+ libpthread is to mark the function weak, test if the function
+ address is non-zero and call the function, otherwise use a fallback.
+ The problem with pthread_atfork is that there is no viable
+ fallback. If you need to do something during fork it has to be done
+ via pthread_atfork. This makes having libpthread optional and using
+ pthread_atfork impossible. We make it possible by providing
+ pthread_atfork in libc_nonshared.a. The real work of pthread_atfork
+ is done by __register_atfork which is already provided in
+ libc_nonshared.a. It's included in libc_nonshared.a because
+ __dso_handle has to be unique to each DSO such that unloading the DSO
+ can unregister the atfork handlers. We build pthread_atfork again
+ under a different file name and include it into libc_nonshared.a and
+ libc.a. We keep pthread_atfork in libpthread_nonshared.a and
+ libpthread.a for compatibility and completeness.
+
+ Applications that can't rely on a new glibc should use the following
+ code to optionally include libpthread and still register a function
+ via pthread_atfork i.e. use __register_atfork directly:
+
+ extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
+ extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
+
+ static int __app_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
+ {
+ return __register_atfork (prepare, parent, child,
+ &__dso_handle == NULL ? NULL : __dso_handle);
+ }
+
+ This code requires glibc 2.3.2 or newer. Previous to 2.3.2 no such
+ interfaces exist and at that point is is impossible to have an
+ optional libpthread and call pthread_atfork.
+
+ This code adds no more ABI requirements than already exist since
+ __dso_handle and __register_atfork are already part of the ABI. */
+#include <pthread_atfork.c>

View File

@ -1,6 +1,6 @@
%define glibcsrcdir glibc-2.18-186-gfd96752
%define glibcversion 2.18.90
%define glibcrelease 9%{?dist}
%define glibcrelease 10%{?dist}
# Pre-release tarballs are pulled in from git using a command that is
# effectively:
#
@ -187,6 +187,12 @@ Patch0043: %{name}-rh1009623.patch
# binutils bug.
Patch0044: %{name}-rh1009145.patch
# Provide localedef with --list-archive FILE support.
Patch0045: %{name}-localedef-arg.patch
# Allow applications to call pthread_atfork without libpthread.so.
Patch0046: %{name}-rh1013801.patch
#
# Patches from upstream
#
@ -544,6 +550,8 @@ package or when debugging this package.
%patch0043 -p1
%patch2028 -p1
%patch0044 -p1
%patch0045 -p1
%patch0046 -p1
##############################################################################
# %%prep - Additional prep required...
@ -1629,6 +1637,11 @@ rm -f *.filelist*
%endif
%changelog
* Thu Oct 3 2013 Carlos O'Donell <carlos@redhat.com> - 2.18.90-9
- Allow applications to use pthread_atfork without explicitly
requiring libpthread.so. (#1013801)
- Support `--list-archive FILE' in localedef utility.
* Thu Oct 3 2013 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.18.90-9
- Define swap_endianness_p in build-locale-archive.