summaryrefslogtreecommitdiff
path: root/regress/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2014-11-23 08:46:50 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2014-11-23 08:46:50 +0000
commitb54cb287e993d980f2843319469c0c1098cc650c (patch)
treea48ddb3b95505a0022e6ad52adf4df3e23bc7829 /regress/lib
parent45bbbcf6bcfa9344c3f4a557b961113ee0128916 (diff)
Add regress for atexit() vs DSO unloading and start on a similar test
for pthread_atfork()
Diffstat (limited to 'regress/lib')
-rw-r--r--regress/lib/csu/Makefile6
-rw-r--r--regress/lib/csu/callbacks/Makefile8
-rw-r--r--regress/lib/csu/callbacks/atexit/Makefile39
-rw-r--r--regress/lib/csu/callbacks/atexit/atexit_test.c119
-rw-r--r--regress/lib/csu/callbacks/atexit/expected.out30
-rw-r--r--regress/lib/csu/callbacks/libaa/Makefile11
-rw-r--r--regress/lib/csu/callbacks/libaa/aa.c49
-rw-r--r--regress/lib/csu/callbacks/libaa/shlib_version2
-rw-r--r--regress/lib/csu/callbacks/libab/Makefile11
-rw-r--r--regress/lib/csu/callbacks/libab/ab.c49
-rw-r--r--regress/lib/csu/callbacks/libab/shlib_version2
-rw-r--r--regress/lib/csu/callbacks/pthread_atfork/Makefile49
-rw-r--r--regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c154
13 files changed, 528 insertions, 1 deletions
diff --git a/regress/lib/csu/Makefile b/regress/lib/csu/Makefile
index 53396e481b7..ac2ae3ae23e 100644
--- a/regress/lib/csu/Makefile
+++ b/regress/lib/csu/Makefile
@@ -1,7 +1,11 @@
-# $OpenBSD: Makefile,v 1.4 2012/09/08 20:09:49 matthew Exp $
+# $OpenBSD: Makefile,v 1.5 2014/11/23 08:46:49 guenther Exp $
SUBDIR+= ctors dtors init_priority
+.if !defined(NOPIC)
+SUBDIR+= callbacks
+.endif
+
install:
.include <bsd.subdir.mk>
diff --git a/regress/lib/csu/callbacks/Makefile b/regress/lib/csu/callbacks/Makefile
new file mode 100644
index 00000000000..48474134a56
--- /dev/null
+++ b/regress/lib/csu/callbacks/Makefile
@@ -0,0 +1,8 @@
+# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $
+
+SUBDIR+= libaa libab atexit
+# not yet: pthread_atfork
+
+install:
+
+.include <bsd.subdir.mk>
diff --git a/regress/lib/csu/callbacks/atexit/Makefile b/regress/lib/csu/callbacks/atexit/Makefile
new file mode 100644
index 00000000000..1d90d336410
--- /dev/null
+++ b/regress/lib/csu/callbacks/atexit/Makefile
@@ -0,0 +1,39 @@
+# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $
+
+.include <bsd.obj.mk>
+
+AA_DIR=${.CURDIR}/../libaa
+AA_OBJDIR!= if [ -d $(AA_DIR)/${__objdir} ]; then \
+ echo "$(AA_DIR)/${__objdir}"; \
+ else \
+ echo "$(AA_DIR)"; \
+ fi
+
+AB_DIR=${.CURDIR}/../libab
+AB_OBJDIR!= if [ -d $(AB_DIR)/${__objdir} ]; then \
+ echo "$(AB_DIR)/${__objdir}"; \
+ else \
+ echo "$(AB_DIR)"; \
+ fi
+
+PROG= atexit_test
+
+SRCS= atexit_test.c
+
+CFLAGS+= -DLIBAA="\"$(AA_OBJDIR)/libaa.so\""
+CFLAGS+= -DLIBAB="\"$(AB_OBJDIR)/libab.so\""
+LDFLAGS+= -Wl,-E
+
+NOMAN=
+
+regress-atexit: ${PROG}
+ for i in 0 1 2 3; do \
+ ./${PROG} $$i || exit; \
+ printf "finished $$i\n\n"; \
+ done | cmp -s - ${.CURDIR}/expected.out
+
+REGRESS_TARGETS=regress-atexit
+
+install:
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/csu/callbacks/atexit/atexit_test.c b/regress/lib/csu/callbacks/atexit/atexit_test.c
new file mode 100644
index 00000000000..3db198c6e70
--- /dev/null
+++ b/regress/lib/csu/callbacks/atexit/atexit_test.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: atexit_test.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */
+
+/*
+ * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <dlfcn.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void *libaa, *libab;
+
+#define CALLBACK(name) static void name(void) { printf("exe "#name"\n"); }
+
+CALLBACK(cleanup1)
+CALLBACK(cleanup2)
+CALLBACK(cleanup3)
+
+static void
+cleanup_dlclose(void)
+{
+ printf("exe cleanup_dlclose begin\n");
+ dlclose(libaa);
+ dlclose(libab);
+ printf("exe cleanup_dlclose end\n");
+}
+
+static void
+aa(void)
+{
+ void (*func)(void) = dlsym(libaa, "aa");
+ if (func == NULL)
+ errx(1, "dlsym(libaa, aa): %s", dlerror());
+ func();
+}
+
+static void
+ab(void)
+{
+ void (*func)(void) = dlsym(libab, "ab");
+ if (func == NULL)
+ errx(1, "dlsym(libab, ab): %s", dlerror());
+ func();
+}
+
+int
+main(int argc, char **argv)
+{
+ int test;
+
+ libaa = dlopen(LIBAA, RTLD_LAZY);
+ if (libaa == NULL)
+ errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAA, dlerror());
+
+ libab = dlopen(LIBAB, RTLD_LAZY);
+ if (libab == NULL)
+ errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAB, dlerror());
+
+ if (argc != 2)
+ test = 0;
+ else
+ test = atoi(argv[1]);
+
+ switch (test) {
+ case 0:
+ /* 1, aa, 2, ab, 3, then exit */
+ atexit(cleanup1);
+ aa();
+ atexit(cleanup2);
+ ab();
+ atexit(cleanup3);
+ exit(0);
+
+ case 1:
+ /* 1, aa, 2, ab, 3, then dlclose aa, then bb */
+ atexit(cleanup1);
+ aa();
+ atexit(cleanup2);
+ ab();
+ atexit(cleanup3);
+ dlclose(libaa);
+ dlclose(libab);
+ exit(0);
+
+ case 2:
+ /* 1, aa, cleanup_dlclose, ab, 3, then exit */
+ atexit(cleanup1);
+ aa();
+ atexit(cleanup_dlclose);
+ ab();
+ atexit(cleanup3);
+ exit(0);
+
+ case 3:
+ /* 1, aa, 2, ab, cleanup_dlclose, then exit */
+ atexit(cleanup1);
+ aa();
+ atexit(cleanup2);
+ ab();
+ atexit(cleanup_dlclose);
+ exit(0);
+
+ }
+
+ return (0);
+}
diff --git a/regress/lib/csu/callbacks/atexit/expected.out b/regress/lib/csu/callbacks/atexit/expected.out
new file mode 100644
index 00000000000..d2cff7fbfac
--- /dev/null
+++ b/regress/lib/csu/callbacks/atexit/expected.out
@@ -0,0 +1,30 @@
+exe cleanup3
+libab cleanup
+exe cleanup2
+libaa cleanup
+exe cleanup1
+finished 0
+
+libaa cleanup
+libab cleanup
+exe cleanup3
+exe cleanup2
+exe cleanup1
+finished 1
+
+exe cleanup3
+libab cleanup
+exe cleanup_dlclose begin
+libaa cleanup
+exe cleanup_dlclose end
+exe cleanup1
+finished 2
+
+exe cleanup_dlclose begin
+libaa cleanup
+libab cleanup
+exe cleanup_dlclose end
+exe cleanup2
+exe cleanup1
+finished 3
+
diff --git a/regress/lib/csu/callbacks/libaa/Makefile b/regress/lib/csu/callbacks/libaa/Makefile
new file mode 100644
index 00000000000..4153c05ff1b
--- /dev/null
+++ b/regress/lib/csu/callbacks/libaa/Makefile
@@ -0,0 +1,11 @@
+# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $
+
+LIB=aa
+SRCS= aa.c
+NOPROFILE=yes
+
+regress: all
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/regress/lib/csu/callbacks/libaa/aa.c b/regress/lib/csu/callbacks/libaa/aa.c
new file mode 100644
index 00000000000..5a84e92cc0b
--- /dev/null
+++ b/regress/lib/csu/callbacks/libaa/aa.c
@@ -0,0 +1,49 @@
+/* $OpenBSD: aa.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */
+
+/*
+ * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#define CALLBACK(file, name) \
+ static void name(void) \
+ { \
+ fprintf(file, "libaa "#name"\n"); \
+ fflush(file); \
+ }
+
+CALLBACK(stdout, cleanup)
+
+void
+aa(void)
+{
+ atexit(cleanup);
+}
+
+static FILE *otherf;
+
+CALLBACK(stdout, atfork_prepare)
+CALLBACK(stdout, atfork_parent)
+CALLBACK(otherf, atfork_child)
+
+void
+aa_atfork(FILE *f)
+{
+ otherf = f;
+ pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
+}
diff --git a/regress/lib/csu/callbacks/libaa/shlib_version b/regress/lib/csu/callbacks/libaa/shlib_version
new file mode 100644
index 00000000000..97c9f92d6b8
--- /dev/null
+++ b/regress/lib/csu/callbacks/libaa/shlib_version
@@ -0,0 +1,2 @@
+major=0
+minor=0
diff --git a/regress/lib/csu/callbacks/libab/Makefile b/regress/lib/csu/callbacks/libab/Makefile
new file mode 100644
index 00000000000..df6be6ada7e
--- /dev/null
+++ b/regress/lib/csu/callbacks/libab/Makefile
@@ -0,0 +1,11 @@
+# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $
+
+LIB=ab
+SRCS= ab.c
+NOPROFILE=yes
+
+regress: all
+
+install:
+
+.include <bsd.lib.mk>
diff --git a/regress/lib/csu/callbacks/libab/ab.c b/regress/lib/csu/callbacks/libab/ab.c
new file mode 100644
index 00000000000..fcf6b79213e
--- /dev/null
+++ b/regress/lib/csu/callbacks/libab/ab.c
@@ -0,0 +1,49 @@
+/* $OpenBSD: ab.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */
+
+/*
+ * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#define CALLBACK(file, name) \
+ static void name(void) \
+ { \
+ fprintf(file, "libab "#name"\n"); \
+ fflush(file); \
+ }
+
+CALLBACK(stdout, cleanup)
+
+void
+ab(void)
+{
+ atexit(cleanup);
+}
+
+static FILE *otherf;
+
+CALLBACK(stdout, atfork_prepare)
+CALLBACK(stdout, atfork_parent)
+CALLBACK(otherf, atfork_child)
+
+void
+ab_atfork(FILE *f)
+{
+ otherf = f;
+ pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
+}
diff --git a/regress/lib/csu/callbacks/libab/shlib_version b/regress/lib/csu/callbacks/libab/shlib_version
new file mode 100644
index 00000000000..97c9f92d6b8
--- /dev/null
+++ b/regress/lib/csu/callbacks/libab/shlib_version
@@ -0,0 +1,2 @@
+major=0
+minor=0
diff --git a/regress/lib/csu/callbacks/pthread_atfork/Makefile b/regress/lib/csu/callbacks/pthread_atfork/Makefile
new file mode 100644
index 00000000000..8e685447d7b
--- /dev/null
+++ b/regress/lib/csu/callbacks/pthread_atfork/Makefile
@@ -0,0 +1,49 @@
+# $OpenBSD: Makefile,v 1.1 2014/11/23 08:46:49 guenther Exp $
+
+.include <bsd.obj.mk>
+
+AA_DIR=${.CURDIR}/../libaa
+AA_OBJDIR!= if [ -d $(AA_DIR)/${__objdir} ]; then \
+ echo "$(AA_DIR)/${__objdir}"; \
+ else \
+ echo "$(AA_DIR)"; \
+ fi
+
+AB_DIR=${.CURDIR}/../libab
+AB_OBJDIR!= if [ -d $(AB_DIR)/${__objdir} ]; then \
+ echo "$(AB_DIR)/${__objdir}"; \
+ else \
+ echo "$(AB_DIR)"; \
+ fi
+
+PROG= pthread_atfork_test
+
+SRCS= pthread_atfork_test.c
+
+CFLAGS+= -DLIBAA="\"$(AA_OBJDIR)/libaa.so\""
+CFLAGS+= -DLIBAB="\"$(AB_OBJDIR)/libab.so\""
+LDFLAGS+= -Wl,-E
+
+LDADD+= -lpthread
+DPADD+= ${LIBPTHREAD}
+
+NOMAN=
+
+CLEANFILES= parent_out child_out
+
+TESTS= 0
+
+regress-pthread_atfork: ${PROG}
+ for i in ${TESTS}; do \
+ ./${PROG} $$i || exit; \
+ printf "finished $$i\n\n"; \
+ printf "finished $$i\n\n" >&3; \
+ done >parent_out 3>child_out
+ cmp -s parent_out ${.CURDIR}/expected_parent.out
+ cmp -s child_out ${.CURDIR}/expected_child.out
+
+REGRESS_TARGETS=regress-pthread_atfork
+
+install:
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c b/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c
new file mode 100644
index 00000000000..c6a93a0e080
--- /dev/null
+++ b/regress/lib/csu/callbacks/pthread_atfork/pthread_atfork_test.c
@@ -0,0 +1,154 @@
+/* $OpenBSD: pthread_atfork_test.c,v 1.1 2014/11/23 08:46:49 guenther Exp $ */
+
+/*
+ * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <dlfcn.h>
+#include <err.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+void *libaa, *libab;
+
+FILE *otherf;
+
+#define CALLBACK(file, name) \
+ static void name(void) \
+ { \
+ fprintf(file, "testp "#name"\n"); \
+ fflush(file); \
+ }
+
+#define ATFORK_CALLBACKS(name) \
+ CALLBACK(stdout, name##_prepare) \
+ CALLBACK(stdout, name##_parent) \
+ CALLBACK(otherf, name##_child)
+
+ATFORK_CALLBACKS(atfork1)
+ATFORK_CALLBACKS(atfork2)
+ATFORK_CALLBACKS(atfork3)
+
+static void
+atfork_dlclose(void)
+{
+ printf("exe atfork_dlclose begin\n");
+ dlclose(libaa);
+ dlclose(libab);
+ printf("exe atfork_dlclose end\n");
+ fflush(stdout);
+}
+
+static void
+aa_atfork(void)
+{
+ void (*func)(FILE *) = dlsym(libaa, "aa_atfork");
+ if (func == NULL)
+ errx(1, "dlsym(libaa, aa_atfork): %s", dlerror());
+ func(otherf);
+}
+
+static void
+ab_atfork(void)
+{
+ void (*func)(FILE *) = dlsym(libab, "ab_atfork");
+ if (func == NULL)
+ errx(1, "dlsym(libab, ab_atfork): %s", dlerror());
+ func(otherf);
+}
+
+#define REGISTER(prep, parent, child) \
+ do { \
+ int _r = pthread_atfork(prep, parent, child); \
+ if (_r) \
+ errc(1, _r, "pthread_atfork(%s,%s,%s)", \
+ #prep, #parent, #child); \
+ } while (0)
+
+#define REGISTER_ALL(name) \
+ REGISTER(name##_prepare, name##_parent, name##_child)
+
+int
+main(int argc, char **argv)
+{
+ pid_t pid;
+ int test;
+
+ otherf = fdopen(3, "w");
+ if (otherf == NULL)
+ otherf = stderr;
+
+ libaa = dlopen(LIBAA, RTLD_LAZY);
+ if (libaa == NULL)
+ errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAA, dlerror());
+
+ libab = dlopen(LIBAB, RTLD_LAZY);
+ if (libab == NULL)
+ errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAB, dlerror());
+
+ if (argc != 2)
+ test = 0;
+ else
+ test = atoi(argv[1]);
+
+ switch (test) {
+ case 0:
+ /* 1, aa, 2, ab, 3, then fork */
+ REGISTER_ALL(atfork1);
+ aa_atfork();
+ REGISTER_ALL(atfork2);
+ ab_atfork();
+ REGISTER_ALL(atfork3);
+ break;
+
+ case 1:
+ /* 1, aa, 2, ab, 3, then dlclose aa and bb, then fork */
+ REGISTER_ALL(atfork1);
+ aa_atfork();
+ REGISTER_ALL(atfork2);
+ ab_atfork();
+ REGISTER_ALL(atfork3);
+ dlclose(libaa);
+ dlclose(libab);
+ break;
+
+ case 2:
+ /* 1, aa, atfork_dlclose, ab, 3, then fork */
+ REGISTER_ALL(atfork1);
+ aa_atfork();
+ REGISTER(atfork_dlclose, NULL, NULL);
+ ab_atfork();
+ REGISTER_ALL(atfork3);
+ break;
+
+ case 3:
+ /* 1, aa, 2, ab, atfork_dlclose, then fork */
+ REGISTER_ALL(atfork1);
+ aa_atfork();
+ REGISTER_ALL(atfork2);
+ ab_atfork();
+ REGISTER(atfork_dlclose, NULL, NULL);
+ break;
+
+ }
+
+ fflush(stdout);
+ fflush(otherf);
+ pid = fork();
+
+ return (0);
+}