From patchwork Thu Feb 11 15:26:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 42017 X-Patchwork-Delegate: fweimer@redhat.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 995FB3871016; Thu, 11 Feb 2021 15:26:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 995FB3871016 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1613057214; bh=QpTuPHkn2LG01BSwvP/vo1xdgTKV3IS79a2/qP6KyoQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=l5YCPu3Nsfzz5WckWp2OcZy/cKqLt/Oq/jfHdNQDcdt7/wM9U10n3XwchlUqNE5Kk nZC1d8ACQSM9acUBx1g4QMYYt8wk3YxaCyj0BFGuYrRqS/BpF5Wv/TDLrmrwxz76B8 QWJIjBPbVyATs0vfV2F++c4qTl5iEenRlMrTGpOw= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) by sourceware.org (Postfix) with ESMTPS id 40E8D386F465 for ; Thu, 11 Feb 2021 15:26:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 40E8D386F465 Received: by mail-qt1-x830.google.com with SMTP id d3so4374914qtr.10 for ; Thu, 11 Feb 2021 07:26:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QpTuPHkn2LG01BSwvP/vo1xdgTKV3IS79a2/qP6KyoQ=; b=bUfH7O27JwG5EpIGwO+grj9SEKt1m198ezcj/PCfPeE3ybvcEUuFQEw+QGOmafGSYD ADrJtoDzJJ8wCOK+D5jkCX/OvyK5fZth4DJdc3NjEOlwAfKAwKWiXdGk6qOet1bY3dPT qmEPPILog1dO8+sxoBXBtp+c3/VnQ2YTU709UCfYOZfdsvkoP2Ce2COHUp8uNQFLyoDQ ihw+YWNHV1B5tHqWQv801fn3HgmQz+j+rvgZ/u4VKsesYCVhaBjAvJmKCp+cd1fkFPpT kM9wqe4agft2Ih1p0jRUla6GowKyVGe0HLafA6ih8rcXSWfhcdDICIcJx+oHtk4MlGd8 l/nw== X-Gm-Message-State: AOAM530m1710iNKuIEXIoTzxZhPRP7UEbffOBHq72vAiHSUVwWCc0W9u WvM+MGQOHuq3OG9Dd5SwJLL8xUfp++H19A== X-Google-Smtp-Source: ABdhPJwA8fzyvOKXwz3qLKnyjqplTAqSCNsmun4X9x+P4xx8cCp8Y0SJ+NasmykyQyMgxS66ztuVKw== X-Received: by 2002:ac8:4751:: with SMTP id k17mr8081694qtp.46.1613057207429; Thu, 11 Feb 2021 07:26:47 -0800 (PST) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id k129sm4229703qkf.108.2021.02.11.07.26.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 11 Feb 2021 07:26:47 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH v2] posix: Add _Fork [BZ #4737] Date: Thu, 11 Feb 2021 12:26:41 -0300 Message-Id: <20210211152641.2330920-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210202151134.2123748-8-adhemerval.zanella@linaro.org> References: <20210202151134.2123748-8-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Changes from previous version: * Added NEWS and manual entry. --- Austin Group issue 62 [1] droped the async-signal-safe requirement for fork and provided a async-signal-safe _Fork replacement that does not run the atfork handlers. It will be included in the future POSIX standard. It allow to close a long standing issue to make fork AS-safe (BZ#4737). As indicated on the bug, besides the internal lock for the atfork handlers itself; there is no guarantee that the handlers itself will not introduce more AS-safe issues. The idea is synchronize fork with the required internal locks to allow children in multithread processes to use mostly of standard function (even though POSIX states only AS-safe function should be used). On signal handles, _Fork should be used intead and only AS-safe functions should be used. For testing, the new tst-_Fork only check basic usage. I also added a new tst-mallocfork3 which uses the same strategy to check for deadlock of tst-mallocfork2 but using threads instead of subprocesses (and it does deadlock if it replaces _Fork with fork). [1] https://austingroupbugs.net/view.php?id=62 --- NEWS | 8 + malloc/Makefile | 3 + malloc/tst-mallocfork3.c | 213 +++++++++++++++++ manual/process.texi | 39 ++-- posix/Makefile | 3 +- posix/Versions | 3 + posix/fork.c | 6 +- posix/tst-_Fork.c | 218 ++++++++++++++++++ posix/unistd.h | 7 + sysdeps/mach/hurd/i386/libc.abilist | 1 + sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 + sysdeps/unix/sysv/linux/alpha/libc.abilist | 1 + sysdeps/unix/sysv/linux/arc/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/libc.abilist | 1 + sysdeps/unix/sysv/linux/csky/libc.abilist | 1 + sysdeps/unix/sysv/linux/hppa/libc.abilist | 1 + sysdeps/unix/sysv/linux/i386/libc.abilist | 1 + sysdeps/unix/sysv/linux/ia64/libc.abilist | 1 + .../sysv/linux/m68k/coldfire/libc.abilist | 1 + .../unix/sysv/linux/m68k/m680x0/libc.abilist | 1 + .../sysv/linux/microblaze/be/libc.abilist | 1 + .../sysv/linux/microblaze/le/libc.abilist | 1 + .../sysv/linux/mips/mips32/fpu/libc.abilist | 1 + .../sysv/linux/mips/mips32/nofpu/libc.abilist | 1 + .../sysv/linux/mips/mips64/n32/libc.abilist | 1 + .../sysv/linux/mips/mips64/n64/libc.abilist | 1 + sysdeps/unix/sysv/linux/nios2/libc.abilist | 1 + .../linux/powerpc/powerpc32/fpu/libc.abilist | 1 + .../powerpc/powerpc32/nofpu/libc.abilist | 1 + .../linux/powerpc/powerpc64/be/libc.abilist | 1 + .../linux/powerpc/powerpc64/le/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv32/libc.abilist | 1 + .../unix/sysv/linux/riscv/rv64/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-32/libc.abilist | 1 + .../unix/sysv/linux/s390/s390-64/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/libc.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/libc.abilist | 1 + .../sysv/linux/sparc/sparc32/libc.abilist | 1 + .../sysv/linux/sparc/sparc64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/64/libc.abilist | 1 + .../unix/sysv/linux/x86_64/x32/libc.abilist | 1 + 42 files changed, 515 insertions(+), 18 deletions(-) create mode 100644 malloc/tst-mallocfork3.c create mode 100644 posix/tst-_Fork.c diff --git a/NEWS b/NEWS index 85e84fe536..b196dd2474 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,14 @@ Major new features: constant on Linux. MINSIGSTKSZ is redefined to sysconf(_SC_MINSIGSTKSZ) and SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ). +* The function _Fork has been added as a async-signal-safe fork + replacement since Austin Group issue 62 droped the async-signal-safe + requirement for fork (and it will be included in the future POSIX + standard). The new _Fork symbol does not issue any atfork handler neither + reset any internal state or lock (such as the malloc one) and only + setup a minimal state required to call async-signal-safe functions (such + as raise or execve). This function is currently a GNU extension. + Deprecated and removed features, and other changes affecting compatibility: [Add deprecations, removals and changes affecting compatibility here] diff --git a/malloc/Makefile b/malloc/Makefile index 583bbefb0d..42852f47a2 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -31,6 +31,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-malloc-backtrace tst-malloc-thread-exit \ tst-malloc-thread-fail tst-malloc-fork-deadlock \ tst-mallocfork2 \ + tst-mallocfork3 \ tst-interpose-nothread \ tst-interpose-thread \ tst-alloc_buffer \ @@ -110,6 +111,8 @@ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes)) $(objpfx)tst-malloc-backtrace: $(shared-thread-library) $(objpfx)tst-malloc-thread-exit: $(shared-thread-library) $(objpfx)tst-malloc-thread-fail: $(shared-thread-library) +$(objpfx)tst-mallocfork3: $(shared-thread-library) +$(objpfx)tst-mallocfork3-mcheck: $(shared-thread-library) $(objpfx)tst-malloc-fork-deadlock: $(shared-thread-library) $(objpfx)tst-malloc-stats-cancellation: $(shared-thread-library) $(objpfx)tst-malloc-backtrace-mcheck: $(shared-thread-library) diff --git a/malloc/tst-mallocfork3.c b/malloc/tst-mallocfork3.c new file mode 100644 index 0000000000..4ac99eea43 --- /dev/null +++ b/malloc/tst-mallocfork3.c @@ -0,0 +1,213 @@ +/* Test case for async-signal-safe _Fork (with respect to malloc). + Copyright (C) 2021 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 + 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; see the file COPYING.LIB. If + not, see . */ + +/* This test is similar to tst-mallocfork2.c, but specifically stress + the async-signal-safeness of _Fork on multithread environment. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* How many malloc objects to keep arond. */ +enum { malloc_objects = 1009 }; + +/* The maximum size of an object. */ +enum { malloc_maximum_size = 70000 }; + +/* How many iterations the test performs before exiting. */ +enum { iterations = 10000 }; + +/* Barrier for synchronization with the threads sending SIGUSR1 + signals, to make it more likely that the signals arrive during a + fork/free/malloc call. */ +static pthread_barrier_t barrier; + +/* Set to 1 if SIGUSR1 is received. Used to detect a signal during + fork/free/malloc. */ +static volatile sig_atomic_t sigusr1_received; + +/* Periodically set to 1, to indicate that the thread is making + progress. Checked by liveness_signal_handler. */ +static volatile sig_atomic_t progress_indicator = 1; + +/* Set to 1 if an error occurs in the signal handler. */ +static volatile sig_atomic_t error_indicator = 0; + +static void +sigusr1_handler (int signo) +{ + sigusr1_received = 1; + + /* Perform a fork with a trivial subprocess. */ + pid_t pid = _Fork (); + if (pid == -1) + { + write_message ("error: fork\n"); + error_indicator = 1; + return; + } + if (pid == 0) + _exit (0); + int status; + int ret = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (ret < 0) + { + write_message ("error: waitpid\n"); + error_indicator = 1; + return; + } + if (status != 0) + { + write_message ("error: unexpected exit status from subprocess\n"); + error_indicator = 1; + return; + } +} + +static void +liveness_signal_handler (int signo) +{ + if (progress_indicator) + progress_indicator = 0; + else + write_message ("warning: thread seems to be stuck\n"); +} + +struct signal_send_args +{ + pthread_t target; + int signo; + bool sleep; +}; +#define SIGNAL_SEND_GET_ARG(arg, field) \ + (((struct signal_send_args *)(arg))->field) + +/* Send SIGNO to the parent thread. If SLEEP, wait a second between + signals, otherwise use barriers to delay sending signals. */ +static void * +signal_sender (void *args) +{ + int signo = SIGNAL_SEND_GET_ARG (args, signo); + bool sleep = SIGNAL_SEND_GET_ARG (args, sleep); + + pthread_t target = SIGNAL_SEND_GET_ARG (args, target); + while (true) + { + if (!sleep) + xpthread_barrier_wait (&barrier); + xpthread_kill (target, signo); + if (sleep) + usleep (1 * 1000 * 1000); + else + xpthread_barrier_wait (&barrier); + } + return NULL; +} + +static pthread_t sigusr1_sender[5]; +static pthread_t sigusr2_sender; + +static int +do_test (void) +{ + xsignal (SIGUSR1, sigusr1_handler); + xsignal (SIGUSR2, liveness_signal_handler); + + pthread_t self = pthread_self (); + + struct signal_send_args sigusr2_args = { self, SIGUSR2, true }; + sigusr2_sender = xpthread_create (NULL, signal_sender, &sigusr2_args); + + /* Send SIGUSR1 signals from several threads. Hopefully, one + signal will hit one of the ciritical functions. Use a barrier to + avoid sending signals while not running fork/free/malloc. */ + struct signal_send_args sigusr1_args = { self, SIGUSR1, false }; + xpthread_barrier_init (&barrier, NULL, + array_length (sigusr1_sender) + 1); + for (size_t i = 0; i < array_length (sigusr1_sender); ++i) + sigusr1_sender[i] = xpthread_create (NULL, signal_sender, &sigusr1_args); + + void *objects[malloc_objects] = {}; + unsigned int fork_signals = 0; + unsigned int free_signals = 0; + unsigned int malloc_signals = 0; + unsigned int seed = 1; + for (int i = 0; i < iterations; ++i) + { + progress_indicator = 1; + int slot = rand_r (&seed) % malloc_objects; + size_t size = rand_r (&seed) % malloc_maximum_size; + + /* Occasionally do a fork first, to catch deadlocks there as + well (see bug 24161). */ + bool do_fork = (rand_r (&seed) % 7) == 0; + + xpthread_barrier_wait (&barrier); + if (do_fork) + { + sigusr1_received = 0; + pid_t pid = _Fork (); + TEST_VERIFY_EXIT (pid != -1); + if (sigusr1_received) + ++fork_signals; + if (pid == 0) + _exit (0); + int status; + int ret = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (ret < 0) + FAIL_EXIT1 ("waitpid: %m"); + TEST_COMPARE (status, 0); + } + sigusr1_received = 0; + free (objects[slot]); + if (sigusr1_received) + ++free_signals; + sigusr1_received = 0; + objects[slot] = malloc (size); + if (sigusr1_received) + ++malloc_signals; + xpthread_barrier_wait (&barrier); + + if (objects[slot] == NULL || error_indicator != 0) + { + printf ("error: malloc: %m\n"); + return 1; + } + } + + /* Clean up allocations. */ + for (int slot = 0; slot < malloc_objects; ++slot) + free (objects[slot]); + + printf ("info: signals received during fork: %u\n", fork_signals); + printf ("info: signals received during free: %u\n", free_signals); + printf ("info: signals received during malloc: %u\n", malloc_signals); + + return 0; +} + +#define TIMEOUT 100 +#include diff --git a/manual/process.texi b/manual/process.texi index 54e65f76c6..e17149ce60 100644 --- a/manual/process.texi +++ b/manual/process.texi @@ -138,8 +138,8 @@ creating a process and making it run another program. @cindex parent process @cindex subprocess A new processes is created when one of the functions -@code{posix_spawn}, @code{fork}, or @code{vfork} is called. (The -@code{system} and @code{popen} also create new processes internally.) +@code{posix_spawn}, @code{fork}, @code{_Fork} or @code{vfork} is called. +(The @code{system} and @code{popen} also create new processes internally.) Due to the name of the @code{fork} function, the act of creating a new process is sometimes called @dfn{forking} a process. Each new process (the @dfn{child process} or @dfn{subprocess}) is allocated a process @@ -155,9 +155,10 @@ limited information about why the child terminated---for example, its exit status code. A newly forked child process continues to execute the same program as -its parent process, at the point where the @code{fork} call returns. -You can use the return value from @code{fork} to tell whether the program -is running in the parent process or the child. +its parent process, at the point where the @code{fork} or @code{_Fork} +call returns. You can use the return value from @code{fork} or +@code{_Fork} to tell whether the program is running in the parent process +or the child. @cindex process image Having several processes run the same program is only occasionally @@ -249,16 +250,13 @@ It is declared in the header file @file{unistd.h}. @deftypefun pid_t fork (void) @standards{POSIX.1, unistd.h} @safety{@prelim{}@mtsafe{}@asunsafe{@ascuplugin{}}@acunsafe{@aculock{}}} -@c The nptl/.../linux implementation safely collects fork_handlers into -@c an alloca()ed linked list and increments ref counters; it uses atomic -@c ops and retries, avoiding locking altogether. It then takes the -@c IO_list lock, resets the thread-local pid, and runs fork. The parent -@c restores the thread-local pid, releases the lock, and runs parent -@c handlers, decrementing the ref count and signaling futex wait if -@c requested by unregister_atfork. The child bumps the fork generation, -@c sets the thread-local pid, resets cpu clocks, initializes the robust -@c mutex list, the stream locks, the IO_list lock, the dynamic loader -@c lock, runs the child handlers, reseting ref counters to 1, and +@c The posix/fork.c implementation iterates over the fork_handlers +@c using a lock. It then takes the IO_list lock, resets the thread-local +@c pid, and runs fork. The parent releases the lock, and runs parent +@c handlers, and unlocks the internal lock. The child bumps the fork +@c generation, sets the thread-local pid, resets cpu clocks, initializes +@c the robust mutex list, the stream locks, the IO_list lock, the dynamic +@c loader lock, runs the child handlers, reseting ref counters to 1, and @c initializes the fork lock. These are all safe, unless atfork @c handlers themselves are unsafe. The @code{fork} function creates a new process. @@ -322,6 +320,17 @@ process is cleared. (The child process inherits its mask of blocked signals and signal actions from the parent process.) @end itemize +@deftypefun pid_t _Fork (void) +@standards{GNU, unistd.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +The @code{_Fork} function is similar to @code{fork} but does not issue +any atfork callback registered with @code{pthread_atfork} neither reset +any internal state or locks (such as the malloc one) and only setup a +minimal state required to call async-signal-safe functions (such as raise +or execve). + +It is an async-signal-safe replacement of @code{fork}. +@end deftypefun @deftypefun pid_t vfork (void) @standards{BSD, unistd.h} diff --git a/posix/Makefile b/posix/Makefile index e0a7802012..25cd5bc456 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -114,7 +114,7 @@ test-srcs := globtest tests += wordexp-test tst-exec tst-spawn tst-spawn2 tst-spawn3 endif ifeq (yesyes,$(build-shared)$(have-thread-library)) -tests += tst-getopt-cancel +tests += tst-getopt-cancel tst-_Fork endif tests-static = tst-exec-static tst-spawn-static tests += $(tests-static) @@ -283,6 +283,7 @@ $(objpfx)ptestcases.h: PTESTS PTESTS2C.sed $(objpfx)runptests.o: $(objpfx)ptestcases.h $(objpfx)tst-getopt-cancel: $(shared-thread-library) +$(objpfx)tst-_Fork: $(shared-thread-library) test-xfail-annexc = yes $(objpfx)annexc.out: $(objpfx)annexc diff --git a/posix/Versions b/posix/Versions index cfd3819966..0ee433299e 100644 --- a/posix/Versions +++ b/posix/Versions @@ -147,6 +147,9 @@ libc { } GLIBC_2.30 { } + GLIBC_2.34 { + _Fork; + } GLIBC_PRIVATE { __libc_fork; __libc_pread; __libc_pwrite; __nanosleep_nocancel; __pause_nocancel; diff --git a/posix/fork.c b/posix/fork.c index 85c819c00f..1c4481f9c2 100644 --- a/posix/fork.c +++ b/posix/fork.c @@ -40,8 +40,10 @@ __libc_fork (void) { /* Determine if we are running multiple threads. We skip some fork handlers in the single-thread case, to make fork safer to use in - signal handlers. POSIX requires that fork is async-signal-safe, - but our current fork implementation is not. */ + signal handlers. Although POSIX has dropped async-signal-safe + requirement for fork (Austin Group tracker issue #62) this is + best effort to make is async-signal-safe at least for single-thread + case. */ bool multiple_threads = __libc_single_threaded == 0; __run_fork_handlers (atfork_run_prepare, multiple_threads); diff --git a/posix/tst-_Fork.c b/posix/tst-_Fork.c new file mode 100644 index 0000000000..29a7ab6aaf --- /dev/null +++ b/posix/tst-_Fork.c @@ -0,0 +1,218 @@ +/* Basic tests for _Fork. + Copyright (C) 2021 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 + 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* For single-thread, _Fork behaves like fork. */ +static int +singlethread_test (void) +{ + const char testdata1[] = "abcdefghijklmnopqrtuvwxz"; + enum { testdatalen1 = array_length (testdata1) }; + const char testdata2[] = "01234567890"; + enum { testdatalen2 = array_length (testdata2) }; + + pid_t ppid = getpid (); + + int tempfd = create_temp_file ("tst-_Fork", NULL); + + /* Check if the opened file is shared between process by read and write + some data on parent and child processes. */ + xwrite (tempfd, testdata1, testdatalen1); + off_t off = xlseek (tempfd, 0, SEEK_CUR); + TEST_COMPARE (off, testdatalen1); + + pid_t pid = _Fork (); + TEST_VERIFY_EXIT (pid != -1); + if (pid == 0) + { + TEST_VERIFY_EXIT (getpid () != ppid); + TEST_COMPARE (getppid(), ppid); + + TEST_COMPARE (xlseek (tempfd, 0, SEEK_CUR), testdatalen1); + + xlseek (tempfd, 0, SEEK_SET); + char buf[testdatalen1]; + TEST_COMPARE (read (tempfd, buf, sizeof (buf)), testdatalen1); + TEST_COMPARE (memcmp (buf, testdata1, testdatalen1), 0); + + xlseek (tempfd, 0, SEEK_SET); + xwrite (tempfd, testdata2, testdatalen2); + + close (tempfd); + + _exit (EXIT_SUCCESS); + } + + int status; + xwaitpid (pid, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_COMPARE (WEXITSTATUS (status), EXIT_SUCCESS); + + TEST_COMPARE (xlseek (tempfd, 0, SEEK_CUR), testdatalen2); + + xlseek (tempfd, 0, SEEK_SET); + char buf[testdatalen2]; + TEST_COMPARE (read (tempfd, buf, sizeof (buf)), testdatalen2); + + TEST_COMPARE (memcmp (buf, testdata2, testdatalen2), 0); + + return 0; +} + + +static volatile sig_atomic_t sigusr1_handler_ran; +static pid_t sig_pid = -1; +#define SIG_PID_EXIT_CODE 20 + +static void +sigusr1_handler (int signum) +{ + TEST_COMPARE (signum, SIGUSR1); + + pid_t ppid = getpid (); + + sig_pid = _Fork (); + TEST_VERIFY_EXIT (sig_pid != -1); + if (sig_pid == 0) + { + TEST_VERIFY_EXIT (getpid () != ppid); + TEST_COMPARE (getppid(), ppid); + + _exit (SIG_PID_EXIT_CODE); + } + + sigusr1_handler_ran = 1; +} + +/* _Fork is async-signal-safe, so check if it can successfully issue + a new process in a signal handler. */ +static int +singlethread_signal_test (void) +{ + xsignal (SIGUSR1, &sigusr1_handler); + /* Assume synchronous signal handling. */ + xraise (SIGUSR1); + TEST_COMPARE (sigusr1_handler_ran, 1); + + int status; + xwaitpid (sig_pid, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_COMPARE (WEXITSTATUS (status), SIG_PID_EXIT_CODE); + + xsignal (SIGUSR1, SIG_DFL); + + return 0; +} + + +static bool atfork_prepare_var; +static bool atfork_parent_var; +static bool atfork_child_var; + +static void +atfork_prepare (void) +{ + atfork_prepare_var = true; +} + +static void +atfork_parent (void) +{ + atfork_parent_var = true; +} + +static void +atfork_child (void) +{ + atfork_child_var = true; +} + +/* Different than fork, _Fork does not execute any pthread_atfork + handlers. */ +static int +singlethread_atfork_test (void) +{ + pthread_atfork (atfork_prepare, atfork_parent, atfork_child); + singlethread_test (); + TEST_COMPARE (atfork_prepare_var, false); + TEST_COMPARE (atfork_parent_var, false); + TEST_COMPARE (atfork_child_var, false); + + return 0; +} + + +static void * +mt_atfork_test (void *args) +{ + singlethread_atfork_test (); + + return NULL; +} + +static int +multithread_atfork_test (void) +{ + pthread_t thr = xpthread_create (NULL, mt_atfork_test, NULL); + xpthread_join (thr); + + return 0; +} + + +static void * +mt_signal_test (void *args) +{ + singlethread_signal_test (); + + return NULL; +} + +static int +multithread_signal_test (void) +{ + pthread_t thr = xpthread_create (NULL, mt_signal_test, NULL); + xpthread_join (thr); + + return 0; +} + + +static int +do_test (void) +{ + singlethread_atfork_test (); + singlethread_signal_test (); + + multithread_atfork_test (); + multithread_signal_test (); + + return 0; +} + +#include diff --git a/posix/unistd.h b/posix/unistd.h index 3f22763379..670d471ac2 100644 --- a/posix/unistd.h +++ b/posix/unistd.h @@ -776,6 +776,13 @@ extern __pid_t fork (void) __THROWNL; extern __pid_t vfork (void) __THROW; #endif /* Use misc or XPG < 7. */ +#ifdef __USE_GNU +/* This is similar to fork, however it does not run the atfork handlers + neither reinitialize any internal locks in multithread case. + Different than fork, _Fork is async-signal-safe. */ +extern __pid_t _Fork (void) __THROWNL; +#endif + /* Return the pathname of the terminal FD is open on, or NULL on errors. The returned storage is good only until the next call to this function. */ diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist index 509e9b7cb0..55834ca18b 100644 --- a/sysdeps/mach/hurd/i386/libc.abilist +++ b/sysdeps/mach/hurd/i386/libc.abilist @@ -2203,6 +2203,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index 4cc1c6a591..dc812707a2 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2171,3 +2171,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 26ad9845e4..3b7e00c87b 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -2253,6 +2253,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist index bb9dfd4daf..7a06fd731c 100644 --- a/sysdeps/unix/sysv/linux/arc/libc.abilist +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist @@ -1931,3 +1931,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist index 3b0a47e967..946568ac6a 100644 --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist @@ -155,6 +155,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist index 9ab3924888..4d2d167974 100644 --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist @@ -152,6 +152,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist index 14a84dac8f..d3092f5702 100644 --- a/sysdeps/unix/sysv/linux/csky/libc.abilist +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist @@ -2115,3 +2115,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index 5c8502f3d3..78a6fe365a 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -2074,6 +2074,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index ddc5837059..f21e646797 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2241,6 +2241,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist index e3b345b803..811da8c935 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -2106,6 +2106,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 25f2d1c08f..1223fc32d7 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -156,6 +156,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0x98 GLIBC_2.4 _IO_2_1_stdin_ D 0x98 diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index c4891479d3..035d8d17fd 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -2186,6 +2186,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist index 143b0163b4..55d7144063 100644 --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist @@ -2166,3 +2166,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist index 13d374a031..f4223a84cf 100644 --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist @@ -2163,3 +2163,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index b2295f1937..1ccb65fe80 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -2157,6 +2157,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index 4c786070d0..27b7489778 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -2155,6 +2155,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index aa9c6a4dca..05b7afe7c8 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -2163,6 +2163,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index 5939588ad5..aa3845e160 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -2157,6 +2157,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index 92556c4237..efe35b8751 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2204,3 +2204,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 26c93dff05..eda0349d39 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -2213,6 +2213,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index f04b167788..c51540783d 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -2246,6 +2246,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist index c2ca00709e..a508ef7e7a 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist @@ -2076,6 +2076,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist index 0ea50dc851..9366d54213 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist @@ -2366,3 +2366,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist index 0263e284d4..2a427fb493 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist @@ -1933,3 +1933,4 @@ GLIBC_2.33 wprintf F GLIBC_2.33 write F GLIBC_2.33 writev F GLIBC_2.33 wscanf F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist index 1626c5351f..26dcd9ec47 100644 --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist @@ -2133,3 +2133,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index a66426eb4d..753b7a99fa 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -2211,6 +2211,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index ab351873ae..454f8d72ba 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -2112,6 +2112,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist index 22ceaa3d87..fe4d7b31ab 100644 --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist @@ -2081,6 +2081,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist index d36f228192..7ef2df0f07 100644 --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist @@ -2078,6 +2078,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index 59b4313280..380c51907a 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -2202,6 +2202,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 _IO_fprintf F GLIBC_2.4 _IO_printf F GLIBC_2.4 _IO_sprintf F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index 266dcdfa08..3c3ad9188d 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -2129,6 +2129,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index 2744bba4af..aff31183eb 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -2088,6 +2088,7 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F GLIBC_2.4 __confstr_chk F GLIBC_2.4 __fgets_chk F GLIBC_2.4 __fgets_unlocked_chk F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index ce2f4fb72b..fd6e98861c 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2185,3 +2185,4 @@ GLIBC_2.33 mknod F GLIBC_2.33 mknodat F GLIBC_2.33 stat F GLIBC_2.33 stat64 F +GLIBC_2.34 _Fork F