New test: test/many_looping_threads.c

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
diff --git a/test/.gitignore b/test/.gitignore
index 10ee4ed..fba8c9d 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -2,6 +2,7 @@
 clone
 fork
 leaderkill
+many_looping_threads
 mmap_offset_decode
 mtd
 seccomp
diff --git a/test/Makefile b/test/Makefile
index 715c4c1..dbc5008 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,7 +3,8 @@
 PROGS = \
     vfork fork sig skodic clone leaderkill childthread \
     sigkill_rain wait_must_be_interruptible threaded_execve \
-    mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap
+    mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap \
+    many_looping_threads
 
 all: $(PROGS)
 
@@ -11,6 +12,8 @@
 
 childthread: LDFLAGS += -pthread
 
+many_looping_threads: LDFLAGS += -pthread
+
 clean distclean:
 	rm -f *.o core $(PROGS) *.gdb
 
diff --git a/test/many_looping_threads.c b/test/many_looping_threads.c
new file mode 100644
index 0000000..918bd9d
--- /dev/null
+++ b/test/many_looping_threads.c
@@ -0,0 +1,49 @@
+// This testcase, when run with large number of threads
+// under stace -f, may never finish because strace does not
+// ensure any fairness in thread scheduling:
+// it restarts threads as they stop. If daughter threads crowd out
+// the "mother" and _they_ get continually restarted by strace,
+// the end of spawning loop will never be reached.
+//
+// Also, it is a testcase which triggers the
+// "strace: Exit of unknown pid 32457 seen"
+// message when on testcase exit, strace sees deaths of newly-attached
+// threads _before_ their first syscall stop.
+//
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static int thd_no;
+
+static void *sub_thd(void *c)
+{
+	dprintf(1, "sub-thread %d created\n", ++thd_no);
+	for (;;)
+		getuid();
+	return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+	int i;
+	pthread_t *thd;
+	int num_threads = 1;
+
+	if (argv[1])
+		num_threads = atoi(argv[1]);
+
+	thd = malloc(num_threads * sizeof(thd[0]));
+	dprintf(1, "test start, num_threads:%d...\n", num_threads);
+
+	for (i = 0; i < num_threads; i++) {
+		pthread_create(&thd[i], NULL, sub_thd, NULL);
+		dprintf(1, "after pthread_create\n");
+	}
+
+	/* Exit. This kills all threads */
+	return 0;
+}