From c2021d0b305d436734709186c8c5dca254f77770 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Thu, 3 Oct 2013 05:22:51 -0400 Subject: [PATCH] Resolves: #1013801 - Allow applications to use pthread_atfork without explicitly requiring libpthread.so. (#1013801) - Support `--list-archive FILE' in localedef utility. --- build-locale-archive.c | 21 ++++-- glibc-localedef-arg.patch | 140 ++++++++++++++++++++++++++++++++++++++ glibc-rh1013801.patch | 90 ++++++++++++++++++++++++ glibc.spec | 15 +++- 4 files changed, 259 insertions(+), 7 deletions(-) create mode 100644 glibc-localedef-arg.patch create mode 100644 glibc-rh1013801.patch diff --git a/build-locale-archive.c b/build-locale-archive.c index 3818485..0c218b9 100644 --- a/build-locale-archive.c +++ b/build-locale-archive.c @@ -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); } diff --git a/glibc-localedef-arg.patch b/glibc-localedef-arg.patch new file mode 100644 index 0000000..37680e4 --- /dev/null +++ b/glibc-localedef-arg.patch @@ -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) diff --git a/glibc-rh1013801.patch b/glibc-rh1013801.patch new file mode 100644 index 0000000..532589c --- /dev/null +++ b/glibc-rh1013801.patch @@ -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 , 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 ++ . */ ++ ++/* 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 diff --git a/glibc.spec b/glibc.spec index d471296..4ba39de 100644 --- a/glibc.spec +++ b/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 - 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 - 2.18.90-9 - Define swap_endianness_p in build-locale-archive.