Browse Source

tests: check tracing of looping threads

* test/many_looping_threads.c: Remove.
* test/.gitignore: Remove many_looping_threads.
* test/Makefile (PROGS): Likewise.
(many_looping_threads): Remove.
* tests/looping_threads.c: New file.
* tests/looping_threads.test: New test.
* tests/.gitignore: Add looping_threads.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(looping_threads_LDADD): New variable.
(MISC_TESTS, XFAIL_TESTS): Add looping_threads.test.
Dmitry V. Levin 1 year ago
parent
commit
b307a94e09
7 changed files with 166 additions and 55 deletions
  1. 0
    1
      test/.gitignore
  2. 1
    4
      test/Makefile
  3. 0
    49
      test/many_looping_threads.c
  4. 1
    0
      tests/.gitignore
  5. 5
    1
      tests/Makefile.am
  6. 121
    0
      tests/looping_threads.c
  7. 38
    0
      tests/looping_threads.test

+ 0
- 1
test/.gitignore View File

@@ -1,7 +1,6 @@
1 1
 childthread
2 2
 clone
3 3
 leaderkill
4
-many_looping_threads
5 4
 mmap_offset_decode
6 5
 mtd
7 6
 seccomp

+ 1
- 4
test/Makefile View File

@@ -3,8 +3,7 @@ CFLAGS += -Wall
3 3
 PROGS = \
4 4
     sig skodic clone leaderkill childthread \
5 5
     sigkill_rain wait_must_be_interruptible threaded_execve \
6
-    mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap \
7
-    many_looping_threads
6
+    mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap
8 7
 
9 8
 all: $(PROGS)
10 9
 
@@ -12,8 +11,6 @@ leaderkill: LDFLAGS += -pthread
12 11
 
13 12
 childthread: LDFLAGS += -pthread
14 13
 
15
-many_looping_threads: LDFLAGS += -pthread
16
-
17 14
 clean distclean:
18 15
 	rm -f *.o core $(PROGS) *.gdb
19 16
 

+ 0
- 49
test/many_looping_threads.c View File

@@ -1,49 +0,0 @@
1
-// This testcase, when run with large number of threads
2
-// under stace -f, may never finish because strace does not
3
-// ensure any fairness in thread scheduling:
4
-// it restarts threads as they stop. If daughter threads crowd out
5
-// the "mother" and _they_ get continually restarted by strace,
6
-// the end of spawning loop will never be reached.
7
-//
8
-// Also, it is a testcase which triggers the
9
-// "strace: Exit of unknown pid 32457 seen"
10
-// message when on testcase exit, strace sees deaths of newly-attached
11
-// threads _before_ their first syscall stop.
12
-//
13
-#include <stdio.h>
14
-#include <pthread.h>
15
-#include <unistd.h>
16
-#include <sys/types.h>
17
-#include <signal.h>
18
-#include <stdlib.h>
19
-
20
-static int thd_no;
21
-
22
-static void *sub_thd(void *c)
23
-{
24
-	dprintf(1, "sub-thread %d created\n", ++thd_no);
25
-	for (;;)
26
-		getuid();
27
-	return NULL;
28
-}
29
-
30
-int main(int argc, char *argv[])
31
-{
32
-	int i;
33
-	pthread_t *thd;
34
-	int num_threads = 1;
35
-
36
-	if (argv[1])
37
-		num_threads = atoi(argv[1]);
38
-
39
-	thd = malloc(num_threads * sizeof(thd[0]));
40
-	dprintf(1, "test start, num_threads:%d...\n", num_threads);
41
-
42
-	for (i = 0; i < num_threads; i++) {
43
-		pthread_create(&thd[i], NULL, sub_thd, NULL);
44
-		dprintf(1, "after pthread_create\n");
45
-	}
46
-
47
-	/* Exit. This kills all threads */
48
-	return 0;
49
-}

+ 1
- 0
tests/.gitignore View File

@@ -224,6 +224,7 @@ list_sigaction_signum
224 224
 llseek
225 225
 localtime
226 226
 lookup_dcookie
227
+looping_threads
227 228
 lseek
228 229
 lstat
229 230
 lstat64

+ 5
- 1
tests/Makefile.am View File

@@ -110,6 +110,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
110 110
 	ksysent \
111 111
 	list_sigaction_signum \
112 112
 	localtime \
113
+	looping_threads \
113 114
 	mmsg-silent \
114 115
 	mmsg_name-v \
115 116
 	msg_control-v \
@@ -174,6 +175,7 @@ fstat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
174 175
 fstatat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
175 176
 ftruncate64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
176 177
 localtime_LDADD = $(clock_LIBS) $(LDADD)
178
+looping_threads_LDADD = -lpthread $(LDADD)
177 179
 lstat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
178 180
 mmap64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
179 181
 mmap64_Xabbrev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
@@ -310,6 +312,7 @@ MISC_TESTS = \
310 312
 	kill_child.test \
311 313
 	ksysent.test \
312 314
 	localtime.test \
315
+	looping_threads.test \
313 316
 	opipe.test \
314 317
 	options-syntax.test \
315 318
 	pc.test \
@@ -351,7 +354,8 @@ TESTS = $(GEN_TESTS) $(DECODER_TESTS) $(MISC_TESTS) $(STACKTRACE_TESTS)
351 354
 XFAIL_TESTS_ =
352 355
 XFAIL_TESTS_m32 = $(STACKTRACE_TESTS)
353 356
 XFAIL_TESTS_mx32 = $(STACKTRACE_TESTS)
354
-XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) $(XFAIL_TESTS_$(ARCH))
357
+XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) $(XFAIL_TESTS_$(ARCH)) \
358
+	      looping_threads.test
355 359
 
356 360
 TEST_LOG_COMPILER = env
357 361
 AM_TEST_LOG_FLAGS = STRACE_ARCH=$(ARCH) STRACE_NATIVE_ARCH=$(NATIVE_ARCH) \

+ 121
- 0
tests/looping_threads.c View File

@@ -0,0 +1,121 @@
1
+/*
2
+ * Check tracing of looping threads.
3
+ *
4
+ * Copyright (c) 2009-2019 The strace developers.
5
+ * All rights reserved.
6
+ *
7
+ * SPDX-License-Identifier: GPL-2.0-or-later
8
+ */
9
+
10
+#include "tests.h"
11
+#include <assert.h>
12
+#include <errno.h>
13
+#include <pthread.h>
14
+#include <signal.h>
15
+#include <stdio.h>
16
+#include <stdlib.h>
17
+#include <unistd.h>
18
+#include <sys/wait.h>
19
+
20
+static void *
21
+thread(void *arg)
22
+{
23
+	for (;;)
24
+		getuid();
25
+	return arg;
26
+}
27
+
28
+int
29
+main(int ac, const char *av[])
30
+{
31
+	assert(ac == 3);
32
+
33
+	int timeout = atoi(av[1]);
34
+	assert(timeout > 0);
35
+
36
+	int num_threads = atoi(av[2]);
37
+	assert(num_threads > 0);
38
+
39
+	/*
40
+	 * Unblock all signals.
41
+	 */
42
+	static sigset_t mask;
43
+	if (sigprocmask(SIG_SETMASK, &mask, NULL))
44
+		perror_msg_and_fail("sigprocmask");
45
+
46
+	/*
47
+	 * Reset SIGALRM and SIGHUP signal handlers.
48
+	 */
49
+	static const struct sigaction sa_def = { .sa_handler = SIG_DFL };
50
+	if (sigaction(SIGHUP, &sa_def, NULL))
51
+		perror_msg_and_fail("sigaction SIGHUP");
52
+	if (sigaction(SIGALRM, &sa_def, NULL))
53
+		perror_msg_and_fail("sigaction SIGALRM");
54
+
55
+	/*
56
+	 * Create a new process group.
57
+	 */
58
+	if (setpgid(0, 0))
59
+		perror_msg_and_fail("setpgid");
60
+
61
+	/*
62
+	 * Set an alarm clock.
63
+	 */
64
+	alarm(timeout);
65
+
66
+	/*
67
+	 * When the main process terminates, the process group becomes orphaned.
68
+	 * If any member of the orphaned process group is stopped, then
69
+	 * a SIGHUP signal followed by a SIGCONT signal is sent to each process
70
+	 * in the orphaned process group.
71
+	 * Create a process in a stopped state to activate this behaviour.
72
+	 */
73
+	const pid_t stopped = fork();
74
+	if (stopped < 0)
75
+		perror_msg_and_fail("fork");
76
+	if (!stopped) {
77
+		raise(SIGSTOP);
78
+		_exit(0);
79
+	}
80
+
81
+	/*
82
+	 * Wait for the process to stop.
83
+	 */
84
+	int status;
85
+	if (waitpid(stopped, &status, WUNTRACED) != stopped)
86
+		perror_msg_and_fail("waitpid WUNTRACED");
87
+	if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
88
+                error_msg_and_fail("waitpid WUNTRACED: "
89
+				   "unexpected wait status %d", status);
90
+	/*
91
+	 * Create all threads in a subprocess, this guarantees that
92
+	 * their tracer will not be their parent.
93
+	 */
94
+	pid_t pid = fork();
95
+	if (pid < 0)
96
+		perror_msg_and_fail("fork");
97
+	if (!pid) {
98
+		for (int i = 0; i < num_threads; i++) {
99
+			pthread_t t;
100
+			if ((errno = pthread_create(&t, NULL, thread, NULL))) {
101
+				if (EAGAIN == errno)
102
+					break;
103
+				perror_msg_and_fail("pthread_create #%d", i);
104
+			}
105
+		}
106
+
107
+		/* This terminates all threads created above.  */
108
+		_exit(0);
109
+	}
110
+
111
+	if (waitpid(pid, &status, 0) != pid)
112
+		perror_msg_and_fail("waitpid");
113
+	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
114
+                error_msg_and_fail("waitpid: unexpected wait status %d",
115
+				   status);
116
+
117
+	/*
118
+	 * Make the process group orphaned.
119
+	 */
120
+	return 0;
121
+}

+ 38
- 0
tests/looping_threads.test View File

@@ -0,0 +1,38 @@
1
+#!/bin/sh
2
+#
3
+# Check tracing of looping threads.
4
+#
5
+# Copyright (c) 2009-2019 The strace developers.
6
+# All rights reserved.
7
+#
8
+# SPDX-License-Identifier: GPL-2.0-or-later
9
+
10
+. "${srcdir=.}/init.sh"
11
+. "${srcdir=.}/PTRACE_SEIZE.sh"
12
+
13
+run_prog ../orphaned_process_group > /dev/null
14
+
15
+run_prog_skip_if_failed date +%s > /dev/null
16
+s0="$(date +%s)"
17
+
18
+check_prog nproc
19
+inc="$(nproc)"
20
+[ "$inc" -ge 1 ] || inc=1
21
+
22
+timeout_2="$(($TIMEOUT_DURATION/2))"
23
+timeout_8="$(($TIMEOUT_DURATION/8))"
24
+nproc=1
25
+
26
+run_prog "../$NAME" "$timeout_8" "$nproc"
27
+
28
+while :; do
29
+	run_strace -f -qq -enone -esignal=none "../$NAME" "$timeout_2" "$nproc"
30
+
31
+	s1="$(date +%s)"
32
+	[ "$(($s1-$s0))" -lt "$timeout_8" ] ||
33
+		break
34
+
35
+	nproc="$(($nproc+$inc))"
36
+done
37
+
38
+warn_ "$ME_: nproc=$nproc elapsed=$(($s1-$s0))"

Loading…
Cancel
Save