public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/azanella/atexit-order] stdlib: Testcase to show wrong atexit execution order
@ 2019-07-11 18:56 Adhemerval Zanella
0 siblings, 0 replies; only message in thread
From: Adhemerval Zanella @ 2019-07-11 18:56 UTC (permalink / raw)
To: glibc-cvs
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=3cd72edf63eedb3e95ae24c974e9b500dc5c9fa0
commit 3cd72edf63eedb3e95ae24c974e9b500dc5c9fa0
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu Jul 11 13:45:37 2019 -0300
stdlib: Testcase to show wrong atexit execution order
This testcase is based on the one discussed on libc-help [1]
[1] https://github.com/mulle-nat/ld-so-breakage
The atexit calls are done by the DSO constructors and program expects
the handlers to be executed in the reverse order the library are
loaded.
The issue is _dl_fini might re-sort the order when libraries are
unloaded and the __cxa_finalize (called by __do_global_dtors_aux
set in arrayfini from DSO) might in turn call its registered atexit
in a wrong order.
Diff:
---
stdlib/Makefile | 16 +++++++-
stdlib/test-atexit-order-dabc.c | 38 +++++++++++++++++++
stdlib/test-atexit-order-liba.c | 45 ++++++++++++++++++++++
stdlib/test-atexit-order-libb.c | 33 +++++++++++++++++
stdlib/test-atexit-order-libc.c | 22 +++++++++++
stdlib/test-atexit-order-libd.c | 30 +++++++++++++++
stdlib/test-atexit-order.c | 82 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 265 insertions(+), 1 deletion(-)
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 32f6050..fe5b39a 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -84,6 +84,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tst-cxa_atexit tst-on_exit test-atexit-race \
test-at_quick_exit-race test-cxa_atexit-race \
test-on_exit-race test-dlclose-exit-race \
+ test-atexit-order \
tst-makecontext-align test-bz22786 tst-strtod-nan-sign \
tst-swapcontext1 tst-setcontext4 tst-setcontext5 \
tst-setcontext6 tst-setcontext7 tst-setcontext8 \
@@ -91,6 +92,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
tst-tls-atexit tst-tls-atexit-nodelete
+others := test-atexit-order-dabc
tests-static := tst-secure-getenv
ifeq ($(build-hardcoded-path-in-tests),yes)
@@ -116,7 +118,11 @@ else
tests-unsupported += tst-quick_exit tst-thread-quick_exit
endif
-modules-names = tst-tls-atexit-lib test-dlclose-exit-race-helper
+modules-names = tst-tls-atexit-lib test-dlclose-exit-race-helper \
+ test-atexit-order-liba \
+ test-atexit-order-libb \
+ test-atexit-order-libc \
+ test-atexit-order-libd
extra-test-objs += $(addsuffix .os, $(modules-names))
ifeq ($(build-shared),yes)
@@ -235,6 +241,14 @@ $(objpfx)tst-tls-atexit.out: $(objpfx)tst-tls-atexit-lib.so
$(objpfx)tst-tls-atexit-nodelete: $(shared-thread-library) $(libdl)
$(objpfx)tst-tls-atexit-nodelete.out: $(objpfx)tst-tls-atexit-lib.so
+$(objpfx)test-atexit-order.out: $(objpfx)test-atexit-order-dabc
+test-atexit-order-ARGS = -- $(host-test-program-cmd)
+$(objpfx)test-atexit-order-dabc: $(objpfx)test-atexit-order-libd.so \
+ $(objpfx)test-atexit-order-liba.so \
+ $(objpfx)test-atexit-order-libb.so \
+ $(objpfx)test-atexit-order-libc.so
+$(objpfx)test-atexit-order-libd.so: $(objpfx)test-atexit-order-libb.so
+
$(objpfx)tst-setcontext3.out: tst-setcontext3.sh $(objpfx)tst-setcontext3
$(SHELL) $< $(common-objpfx) '$(test-program-prefix-before-env)' \
'$(run-program-env)' '$(test-program-prefix-after-env)' \
diff --git a/stdlib/test-atexit-order-dabc.c b/stdlib/test-atexit-order-dabc.c
new file mode 100644
index 0000000..c4e666f
--- /dev/null
+++ b/stdlib/test-atexit-order-dabc.c
@@ -0,0 +1,38 @@
+/* Check atexit execution order regarding other exit types.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <errno.h>
+
+extern void set_a_exit_code (int);
+
+int main (int argc, char *argv[])
+{
+ if (argc < 2)
+ exit (EXIT_FAILURE);
+
+ int exit_code = strtol (argv[1], NULL, 10);
+ if (errno == ERANGE || exit_code < 0 || exit_code > 255)
+ exit (EXIT_FAILURE);
+
+ set_a_exit_code (exit_code);
+
+ exit (0);
+
+ return 0;
+}
diff --git a/stdlib/test-atexit-order-liba.c b/stdlib/test-atexit-order-liba.c
new file mode 100644
index 0000000..857787d
--- /dev/null
+++ b/stdlib/test-atexit-order-liba.c
@@ -0,0 +1,45 @@
+/* Helper module for atexit execution order test.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int exit_code;
+
+static void
+liba_atexit (void)
+{
+ printf ("%s\n", __func__);
+ fflush (stdout);
+ _exit (exit_code);
+}
+
+static void
+__attribute__((constructor))
+liba_constructor (void)
+{
+ printf ("%s\n", __func__);
+ atexit (liba_atexit);
+}
+
+void
+set_a_exit_code (int code)
+{
+ exit_code = code;
+}
diff --git a/stdlib/test-atexit-order-libb.c b/stdlib/test-atexit-order-libb.c
new file mode 100644
index 0000000..80845c5
--- /dev/null
+++ b/stdlib/test-atexit-order-libb.c
@@ -0,0 +1,33 @@
+/* Helper module for atexit execution order test.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+libb_atexit (void)
+{
+ printf ("%s\n", __func__);
+}
+
+void
+init_b (void)
+{
+ printf ("%s\n", __func__);
+ atexit (libb_atexit);
+}
diff --git a/stdlib/test-atexit-order-libc.c b/stdlib/test-atexit-order-libc.c
new file mode 100644
index 0000000..55b2933
--- /dev/null
+++ b/stdlib/test-atexit-order-libc.c
@@ -0,0 +1,22 @@
+/* Helper module for atexit execution order test.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+void
+foo_c (void)
+{
+}
diff --git a/stdlib/test-atexit-order-libd.c b/stdlib/test-atexit-order-libd.c
new file mode 100644
index 0000000..dc479e1
--- /dev/null
+++ b/stdlib/test-atexit-order-libd.c
@@ -0,0 +1,30 @@
+/* Helper module for atexit execution order test.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void init_b (void);
+
+static void
+__attribute__((constructor))
+libb_constructor (void)
+{
+ printf ("%s\n", __func__);
+ init_b ();
+}
diff --git a/stdlib/test-atexit-order.c b/stdlib/test-atexit-order.c
new file mode 100644
index 0000000..4ec4122
--- /dev/null
+++ b/stdlib/test-atexit-order.c
@@ -0,0 +1,82 @@
+/* Check atexit execution order regarding other exit types.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+#include <libgen.h>
+
+#include <support/capture_subprocess.h>
+#include <support/support.h>
+#include <support/check.h>
+
+static int
+do_test (int argc, char *argv[])
+{
+ const int expected_exit_code = 32;
+ char *expected_exit_code_str;
+ char *test_path;
+
+ /* We must have
+ - one or four parameters left if called initially
+ + argv[1]: path for ld.so optional
+ + argv[2]: "--library-path" optional
+ + argv[3]: the library path optional
+ + argv[4/1]: the application name
+ */
+ char *spargv[6];
+ {
+ int i;
+ for (i = 0; i < argc - 2; i++)
+ spargv[i] = argv[i + 1];
+
+ test_path = xasprintf ("%s/%s", dirname (argv[i + 1]),
+ "test-atexit-order-dabc");
+ spargv[i++] = test_path;
+
+ expected_exit_code_str = xasprintf ("%d", expected_exit_code);
+ spargv[i++] = expected_exit_code_str;
+
+ spargv[i] = NULL;
+ }
+
+ struct support_capture_subprocess result =
+ support_capture_subprogram (spargv[0], spargv);
+
+ const char expected[] =
+ "liba_constructor\n"
+ "libb_constructor\n"
+ "init_b\n"
+ "libb_atexit\n"
+ "liba_atexit\n";
+
+ support_capture_subprocess_check (&result, "test-atexit-order",
+ 32, sc_allow_stdout);
+
+ TEST_COMPARE_BLOB (result.out.buffer, result.out.length,
+ expected, sizeof (expected) - 1);
+
+ support_capture_subprocess_free (&result);
+
+ free (expected_exit_code_str);
+ free (test_path);
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2019-07-11 18:56 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-11 18:56 [glibc/azanella/atexit-order] stdlib: Testcase to show wrong atexit execution order Adhemerval Zanella
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).