Resolves: #1013801
- Allow applications to use pthread_atfork without explicitly requiring libpthread.so. (#1013801) - Support `--list-archive FILE' in localedef utility.
This commit is contained in:
parent
13a25e85c0
commit
c2021d0b30
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
|
@ -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>
|
15
glibc.spec
15
glibc.spec
|
@ -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.
|
||||
|
||||
|
|
Loading…
Reference in New Issue