summaryrefslogtreecommitdiffstats
path: root/testsuite/systemtap.base/bz6850.c
diff options
context:
space:
mode:
authorddomingo <ddomingo@redhat.com>2008-10-06 16:19:08 +1000
committerddomingo <ddomingo@redhat.com>2008-10-06 16:19:08 +1000
commit56bf4a62d293f8a353a63833cf945024d1d77ae8 (patch)
tree66d37792213c0e3b7cf5d6a11cdc3800c45bac87 /testsuite/systemtap.base/bz6850.c
parentd77fecabffb83a90c7ef7b6ad81a183beb345330 (diff)
parent5311c037f83f66967f9de4cc66815f93940bb005 (diff)
downloadsystemtap-steved-56bf4a62d293f8a353a63833cf945024d1d77ae8.tar.gz
systemtap-steved-56bf4a62d293f8a353a63833cf945024d1d77ae8.tar.xz
systemtap-steved-56bf4a62d293f8a353a63833cf945024d1d77ae8.zip
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
Diffstat (limited to 'testsuite/systemtap.base/bz6850.c')
-rw-r--r--testsuite/systemtap.base/bz6850.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/testsuite/systemtap.base/bz6850.c b/testsuite/systemtap.base/bz6850.c
new file mode 100644
index 00000000..a8b78110
--- /dev/null
+++ b/testsuite/systemtap.base/bz6850.c
@@ -0,0 +1,87 @@
+/* Regression test for bugzilla 6850 */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define PASS_MARKER "./bz6850_pass"
+
+/* All this in an attempt to defeat gcc's over-aggressive inlining... */
+typedef pid_t (*forker)(int);
+static forker call_chain[];
+
+/*
+ * Both parent and child return from fork2() and fork1(). Both
+ * processes will hit the uretprobe trampolines. The handlers should
+ * run in the parent. With the bug fix in place, the child will return
+ * correctly and do the exec (but won't run the handlers).
+ */
+static pid_t fork2(int ignored)
+{
+ return fork();
+}
+
+static pid_t fork1(int func_index)
+{
+ ++func_index;
+ return call_chain[func_index](func_index); /* fork2() */
+}
+
+static pid_t fork_and_exec2(int func_index)
+{
+ pid_t child;
+ ++func_index;
+ child = call_chain[func_index](func_index); /* fork1() */
+ if (child == 0) {
+ /* I'm the child. Create the marker file. */
+ char *child_args[] = { "/bin/touch", PASS_MARKER, NULL };
+ char *child_env[] = { NULL };
+ execve(child_args[0], child_args, child_env);
+ perror("execve");
+ fprintf(stderr, "FAIL: child couldn't exec.\n");
+ exit(2);
+ }
+ return child;
+}
+
+static pid_t fork_and_exec1(int func_index)
+{
+ ++func_index;
+ return call_chain[func_index](func_index); /* fork_and_exec2() */
+}
+
+static forker call_chain[] = {
+ fork_and_exec1,
+ fork_and_exec2,
+ fork1,
+ fork2,
+ NULL
+};
+
+main()
+{
+ pid_t child, wait_child;
+ int status = 0;
+
+ (void) unlink(PASS_MARKER);
+ child = call_chain[0](0); /* fork_and_exec1() */
+ if (child < 0) {
+ fprintf(stderr, "FAIL: fork_and_exec1() failed.\n");
+ exit(1);
+ }
+ wait_child = wait(&status);
+ if (wait_child != child) {
+ fprintf(stderr, "FAIL: waited for %d but got %d\n",
+ child, wait_child);
+ exit(1);
+ }
+ if (WEXITSTATUS(status) != 0) {
+ fprintf(stderr, "FAIL: child died with status = %d\n",
+ WEXITSTATUS(status));
+ exit(1);
+ }
+ exit(0);
+}