From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-ot1-x32a.google.com (mail-ot1-x32a.google.com [IPv6:2607:f8b0:4864:20::32a]) by sourceware.org (Postfix) with ESMTPS id 6B95A385781D for ; Tue, 13 Jul 2021 21:13:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6B95A385781D Received: by mail-ot1-x32a.google.com with SMTP id e1-20020a9d63c10000b02904b8b87ecc43so291848otl.4 for ; Tue, 13 Jul 2021 14:13:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=kXiCcgGz46xBlgloNFlcFXch50sjHiahxTV8+CGukOg=; b=NQakR+ME3CJrNLg2dwEnX3mEjJ52ciquE2ACuOjsGHe+pqxC3Xnf3B8/pPo56sVo1o +aflBk5slFSc+vHjDhTWUWXmoNSni6jSc9yX+sm3iMOF+DKFt204zbQPwEsFh91PPNK9 YXMpz2QI9CSazRR8hPmAORFG3YMfyOJ8Foa2zMNaY28Ho7HMFUjq0YyFYCP7kJFqyHgc o8htW7o3MtU9AAO0ya8ceTEY7mhU1PnS0swdx8R2rlcPCUTGFALZiOk0BycHDjF22JTe 20TYa4WrJVj5+vl4dr3q0qbE6uV2bg3H7bEzGKcbiLZwzei/Db46QRcQYHKSn7vTupNU cayQ== X-Gm-Message-State: AOAM533wQG9QmfxeRuMUWt2kvqHmTSdLsIbBirir4E1P+kC1oQ/rRhaP FXK7hBs6YqXeaib1FgvsnKGLPKpFkqkNp8qAaA4= X-Google-Smtp-Source: ABdhPJxEzADJ4GVb6WJg0TnubjnKCCg8woT70ogreajywB8vApHGMdlclYtaVaHZG9eb3XI+xtjGbchhd8B89d3QiCo= X-Received: by 2002:a9d:63c6:: with SMTP id e6mr1374316otl.295.1626210785727; Tue, 13 Jul 2021 14:13:05 -0700 (PDT) MIME-Version: 1.0 References: <20210601145516.3553627-1-hjl.tools@gmail.com> <20210601145516.3553627-4-hjl.tools@gmail.com> <6ec9f19a-8e6c-b5e9-859a-e72d21be9d4b@linaro.org> In-Reply-To: <6ec9f19a-8e6c-b5e9-859a-e72d21be9d4b@linaro.org> From: "H.J. Lu" Date: Tue, 13 Jul 2021 14:12:29 -0700 Message-ID: Subject: [PATCH v9] Add static tests for __clone_internal To: Adhemerval Zanella Cc: GNU C Library , Florian Weimer , Noah Goldstein Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-3033.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-List-Received-Date: Tue, 13 Jul 2021 21:13:09 -0000 On Tue, Jul 13, 2021 at 12:33 PM Adhemerval Zanella wrote: > > They are quite similar to the non '-internal' tests, would be better to try > include and reimplement the difference bits that calls the __clone_internal() > intead of replicate all the tests? I'd like to test __clone_internal separately and leave the existing clone tests alone. > On 01/06/2021 11:55, H.J. Lu wrote: > > --- > > sysdeps/unix/sysv/linux/Makefile | 9 ++ > > .../sysv/linux/tst-align-clone-internal.c | 87 +++++++++++ > > sysdeps/unix/sysv/linux/tst-clone2-internal.c | 137 ++++++++++++++++++ > > sysdeps/unix/sysv/linux/tst-clone3-internal.c | 99 +++++++++++++ > > .../unix/sysv/linux/tst-getpid1-internal.c | 133 +++++++++++++++++ > > .../sysv/linux/tst-misalign-clone-internal.c | 86 +++++++++++ > > 6 files changed, 551 insertions(+) > > create mode 100644 sysdeps/unix/sysv/linux/tst-align-clone-internal.c > > create mode 100644 sysdeps/unix/sysv/linux/tst-clone2-internal.c > > create mode 100644 sysdeps/unix/sysv/linux/tst-clone3-internal.c > > create mode 100644 sysdeps/unix/sysv/linux/tst-getpid1-internal.c > > create mode 100644 sysdeps/unix/sysv/linux/tst-misalign-clone-internal.c > > > > diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile > > index 9469868bce..214b912921 100644 > > --- a/sysdeps/unix/sysv/linux/Makefile > > +++ b/sysdeps/unix/sysv/linux/Makefile > > @@ -118,6 +118,15 @@ endif > > > > tests-internal += tst-sigcontext-get_pc > > > > +tests-clone-internal = \ > > + tst-align-clone-internal \ > > + tst-clone2-internal \ > > + tst-clone3-internal \ > > + tst-getpid1-internal \ > > + tst-misalign-clone-internal > > +tests-internal += $(tests-clone-internal) > > +tests-static += $(tests-clone-internal) > > + > > CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables > > > > # Generate the list of SYS_* macros for the system calls (__NR_* > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/tst-align-clone-internal.c b/sysdeps/unix/sysv/linux/tst-align-clone-internal.c > > new file mode 100644 > > index 0000000000..6c3631f3db > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/tst-align-clone-internal.c > > @@ -0,0 +1,87 @@ > > +/* Verify that the clone child stack is properly aligned. > > + 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 > > + > > +static int > > +f (void *arg) > > +{ > > + bool ok = true; > > + > > + puts ("in f"); > > + > > + if (TEST_STACK_ALIGN ()) > > + ok = false; > > + > > + return ok ? 0 : 1; > > +} > > Maybe: > > statit int > f (void *arg) > { > return TEST_STACK_ALIGN () ? 0 : 1; > } Fixed. > > + > > +static int > > +do_test (void) > > +{ > > + bool ok = true; > > + > > + puts ("in main"); > > + > > + if (TEST_STACK_ALIGN ()) > > + ok = false; > > + > > Maybe > > ok = TEST_STACK_ALIGN (); > > But I think this does not really add much, so I think it would be better > to: > > if (! TEST_STACK_ALIGN ()) > FAIL_EXIT1 ("stack alignment failed"); Fixed. > > +#ifdef __ia64__ > > +# define STACK_SIZE 256 * 1024 > > +#else > > +# define STACK_SIZE 128 * 1024 > > +#endif > > + char st[STACK_SIZE] __attribute__ ((aligned)); > > + struct clone_args clone_args = > > + { > > + .stack = (uintptr_t) st, > > + .stack_size = sizeof (st), > > + }; > > + pid_t p = __clone_internal (&clone_args, f, 0); > > + if (p == -1) > > + { > > + printf("clone failed: %m\n"); > > + return 1; > > + } > > Use TEST_VERIFY here: > > TEST_VERIFY (p != -1); Fixed. > > + > > + int e; > > + xwaitpid (p, &e, __WCLONE); > > + if (!WIFEXITED (e)) > > + { > > + if (WIFSIGNALED (e)) > > + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); > > + else > > + puts ("did not terminate correctly"); > > + return 1; > > + } > > + if (WEXITSTATUS (e) != 0) > > + ok = false; > > TEST_VERIFY (WIFEXITED (status)); > TEST_COMPARE (WEXITSTATUS (status), 0); Fixed. > > + > > + return ok ? 0 : 1; > > +} > > + > > +#include > > diff --git a/sysdeps/unix/sysv/linux/tst-clone2-internal.c b/sysdeps/unix/sysv/linux/tst-clone2-internal.c > > new file mode 100644 > > index 0000000000..b8917fe713 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/tst-clone2-internal.c > > @@ -0,0 +1,137 @@ > > +/* Test if CLONE_VM does not change pthread pid/tid field (BZ #19957) > > + 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 > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +static int sig; > > +static int pipefd[2]; > > + > > +static int > > +f (void *a) > > +{ > > + close (pipefd[0]); > > + > > + pid_t ppid = getppid (); > > + pid_t pid = getpid (); > > + pid_t tid = gettid (); > > + > > + if (write (pipefd[1], &ppid, sizeof ppid) != sizeof (ppid)) > > + FAIL_EXIT1 ("write ppid failed\n"); > > + if (write (pipefd[1], &pid, sizeof pid) != sizeof (pid)) > > + FAIL_EXIT1 ("write pid failed\n"); > > + if (write (pipefd[1], &tid, sizeof tid) != sizeof (tid)) > > + FAIL_EXIT1 ("write tid failed\n"); > > + > > + return 0; > > +} > > + > > + > > +static int > > +do_test (void) > > +{ > > + sig = SIGRTMIN; > > + sigset_t ss; > > + sigemptyset (&ss); > > + sigaddset (&ss, sig); > > + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) > > + FAIL_EXIT1 ("sigprocmask failed: %m"); > > + > > + if (pipe2 (pipefd, O_CLOEXEC)) > > + FAIL_EXIT1 ("pipe failed: %m"); > > + > > +#ifdef __ia64__ > > +# define STACK_SIZE 256 * 1024 > > +#else > > +# define STACK_SIZE 128 * 1024 > > +#endif > > + char st[STACK_SIZE] __attribute__ ((aligned)); > > + struct clone_args clone_args = > > + { > > + .stack = (uintptr_t) st, > > + .stack_size = sizeof (st), > > + }; > > + pid_t p = __clone_internal (&clone_args, f, 0); > > + > > + close (pipefd[1]); > > + > > + if (p == -1) > > + FAIL_EXIT1("clone failed: %m"); > > + > > + pid_t ppid, pid, tid; > > + if (read (pipefd[0], &ppid, sizeof pid) != sizeof pid) > > + { > > + kill (p, SIGKILL); > > + FAIL_EXIT1 ("read ppid failed: %m"); > > + } > > + if (read (pipefd[0], &pid, sizeof pid) != sizeof pid) > > + { > > + kill (p, SIGKILL); > > + FAIL_EXIT1 ("read pid failed: %m"); > > + } > > + if (read (pipefd[0], &tid, sizeof tid) != sizeof tid) > > + { > > + kill (p, SIGKILL); > > + FAIL_EXIT1 ("read tid failed: %m"); > > + } > > + > > + close (pipefd[0]); > > + > > + int ret = 0; > > + > > + pid_t own_pid = getpid (); > > + pid_t own_tid = syscall (__NR_gettid); > > + > > + /* Some sanity checks for clone syscall: returned ppid should be current > > + pid and both returned tid/pid should be different from current one. */ > > + if ((ppid != own_pid) || (pid == own_pid) || (tid == own_tid)) > > + FAIL_RET ("ppid=%i pid=%i tid=%i | own_pid=%i own_tid=%i", > > + (int)ppid, (int)pid, (int)tid, (int)own_pid, (int)own_tid); > > + > > + int e; > > + xwaitpid (p, &e, __WCLONE); > > + if (!WIFEXITED (e)) > > + { > > + if (WIFSIGNALED (e)) > > + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); > > + else > > + puts ("did not terminate correctly"); > > + exit (EXIT_FAILURE); > > + } > > + if (WEXITSTATUS (e) != 0) > > + FAIL_EXIT1 ("exit code %d", WEXITSTATUS (e)); > > TEST_VERIFY (WIFEXITED (status)); > TEST_COMPARE (WEXITSTATUS (status), 0); Fixed. > > + > > + return ret; > > +} > > + > > +#include > > diff --git a/sysdeps/unix/sysv/linux/tst-clone3-internal.c b/sysdeps/unix/sysv/linux/tst-clone3-internal.c > > new file mode 100644 > > index 0000000000..2bdbc571e6 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/tst-clone3-internal.c > > @@ -0,0 +1,99 @@ > > +/* Check if clone (CLONE_THREAD) does not call exit_group (BZ #21512) > > + 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 > > +#include > > +#include > > + > > +/* Test if clone call with CLONE_THREAD does not call exit_group. The 'f' > > + function returns '1', which will be used by clone thread to call the > > + 'exit' syscall directly. If _exit is used instead, exit_group will be > > + used and thus the thread group will finish with return value of '1' > > + (where '2' from main thread is expected.). */ > > + > > +static int > > +f (void *a) > > +{ > > + return 1; > > +} > > + > > +/* Futex wait for TID argument, similar to pthread_join internal > > + implementation. */ > > +#define wait_tid(ctid_ptr, ctid_val) \ > > + do { \ > > + __typeof (*(ctid_ptr)) __tid; \ > > + /* We need acquire MO here so that we synchronize with the \ > > + kernel's store to 0 when the clone terminates. */ \ > > + while ((__tid = atomic_load_explicit (ctid_ptr, \ > > + memory_order_acquire)) != 0) \ > > + futex_wait (ctid_ptr, ctid_val); \ > > + } while (0) > > + > > +static inline int > > +futex_wait (int *futexp, int val) > > +{ > > +#ifdef __NR_futex > > + return syscall (__NR_futex, futexp, FUTEX_WAIT, val); > > +#else > > + return syscall (__NR_futex_time64, futexp, FUTEX_WAIT, val); > > +#endif > > +} > > + > > +static int > > +do_test (void) > > +{ > > + char st[1024] __attribute__ ((aligned)); > > + int clone_flags = CLONE_THREAD; > > + /* Minimum required flags to used along with CLONE_THREAD. */ > > + clone_flags |= CLONE_VM | CLONE_SIGHAND; > > + /* We will used ctid to call on futex to wait for thread exit. */ > > + clone_flags |= CLONE_CHILD_CLEARTID; > > + /* Initialize with a known value. ctid is set to zero by the kernel after the > > + cloned thread has exited. */ > > +#define CTID_INIT_VAL 1 > > + pid_t ctid = CTID_INIT_VAL; > > + pid_t tid; > > + > > + struct clone_args clone_args = > > + { > > + .flags = clone_flags & ~CSIGNAL, > > + .exit_signal = clone_flags & CSIGNAL, > > + .stack = (uintptr_t) st, > > + .stack_size = sizeof (st), > > + .child_tid = (uintptr_t) &ctid, > > + }; > > + tid = __clone_internal (&clone_args, f, NULL); > > + if (tid == -1) > > + FAIL_EXIT1 ("clone failed: %m"); > > + > > + wait_tid (&ctid, CTID_INIT_VAL); > > + > > + return 2; > > +} > > + > > +#define EXPECTED_STATUS 2 > > +#include > > diff --git a/sysdeps/unix/sysv/linux/tst-getpid1-internal.c b/sysdeps/unix/sysv/linux/tst-getpid1-internal.c > > new file mode 100644 > > index 0000000000..ee69e52401 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/tst-getpid1-internal.c > > @@ -0,0 +1,133 @@ > > +/* Verify that the parent pid is unchanged by __clone_internal. > > + 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 > > + > > +#ifndef TEST_CLONE_FLAGS > > +#define TEST_CLONE_FLAGS 0 > > +#endif > > + > > +static int sig; > > + > > +static int > > +f (void *a) > > +{ > > + puts ("in f"); > > + union sigval sival; > > + sival.sival_int = getpid (); > > + printf ("pid = %d\n", sival.sival_int); > > + if (sigqueue (getppid (), sig, sival) != 0) > > + return 1; > > + return 0; > > +} > > + > > + > > +static int > > +do_test (void) > > +{ > > + int mypid = getpid (); > > + > > + sig = SIGRTMIN; > > + sigset_t ss; > > + sigemptyset (&ss); > > + sigaddset (&ss, sig); > > + if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0) > > + { > > + printf ("sigprocmask failed: %m\n"); > > + return 1; > > + } > > + > > +#ifdef __ia64__ > > +# define STACK_SIZE 256 * 1024 > > +#else > > +# define STACK_SIZE 128 * 1024 > > +#endif > > + char st[STACK_SIZE] __attribute__ ((aligned)); > > + struct clone_args clone_args = > > + { > > + .flags = TEST_CLONE_FLAGS & ~CSIGNAL, > > + .exit_signal = TEST_CLONE_FLAGS & CSIGNAL, > > + .stack = (uintptr_t) st, > > + .stack_size = sizeof (st), > > + }; > > + pid_t p = __clone_internal (&clone_args, f, 0); > > + if (p == -1) > > + { > > + printf("clone failed: %m\n"); > > + return 1; > > + } > > + printf ("new thread: %d\n", (int) p); > > + > > + siginfo_t si; > > + do > > + if (sigwaitinfo (&ss, &si) < 0) > > + { > > + printf("sigwaitinfo failed: %m\n"); > > + kill (p, SIGKILL); > > + return 1; > > + } > > + while (si.si_signo != sig || si.si_code != SI_QUEUE); > > + > > + int e; > > + xwaitpid (p, &e, __WCLONE); > > + if (!WIFEXITED (e)) > > + { > > + if (WIFSIGNALED (e)) > > + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); > > + else > > + puts ("did not terminate correctly"); > > + return 1; > > + } > > + if (WEXITSTATUS (e) != 0) > > + { > > + printf ("exit code %d\n", WEXITSTATUS (e)); > > + return 1; > > + } > > + > > + if (si.si_int != (int) p) > > + { > > + printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int); > > + kill (p, SIGKILL); > > + return 1; > > + } > > + > > + if (si.si_pid != p) > > + { > > + printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid); > > + kill (p, SIGKILL); > > + return 1; > > + } > > + > > + if (getpid () != mypid) > > + { > > + puts ("my PID changed"); > > + return 1; > > + } > > + > > + return 0; > > +} > > + > > +#include > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/tst-misalign-clone-internal.c b/sysdeps/unix/sysv/linux/tst-misalign-clone-internal.c > > new file mode 100644 > > index 0000000000..6df5fd2cbc > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/tst-misalign-clone-internal.c > > @@ -0,0 +1,86 @@ > > +/* Verify that __clone_internal properly aligns the child stack. > > + 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 > > +#include > > +#include > > + > > +static int > > +check_stack_alignment (void *arg) > > +{ > > + bool ok = true; > > + > > + puts ("in f"); > > + > > + if (TEST_STACK_ALIGN ()) > > + ok = false; > > + > > + return ok ? 0 : 1; > > +} I made a similar change here. > > +static int > > +do_test (void) > > +{ > > + puts ("in do_test"); > > + > > + if (TEST_STACK_ALIGN ()) > > + FAIL_EXIT1 ("stack isn't aligned\n"); > > + > > +#ifdef __ia64__ > > +# define STACK_SIZE (256 * 1024) > > +#else > > +# define STACK_SIZE (128 * 1024) > > +#endif > > + char st[STACK_SIZE + 1]; > > + /* NB: Align child stack to 1 byte. */ > > + char *stack = PTR_ALIGN_UP (&st[0], 2) + 1; > > + struct clone_args clone_args = > > + { > > + .stack = (uintptr_t) stack, > > + .stack_size = STACK_SIZE, > > + }; > > + pid_t p = __clone_internal (&clone_args, check_stack_alignment, 0); > > + > > + /* Clone must not fail. */ > > + TEST_VERIFY_EXIT (p != -1); > > + > > + int e; > > + xwaitpid (p, &e, __WCLONE); > > + if (!WIFEXITED (e)) > > + { > > + if (WIFSIGNALED (e)) > > + printf ("died from signal %s\n", strsignal (WTERMSIG (e))); > > + FAIL_EXIT1 ("process did not terminate correctly"); > > + } > > + > > + if (WEXITSTATUS (e) != 0) > > + FAIL_EXIT1 ("exit code %d", WEXITSTATUS (e)); Likewise. > > + return 0; > > +} > > + > > +#include > > Here is the v9 patch. OK for master? Thanks. -- H.J.