test/sigkill_rain.c: a testcase with lots of async deaths
diff --git a/test/sigkill_rain.c b/test/sigkill_rain.c
new file mode 100644
index 0000000..4306a8a
--- /dev/null
+++ b/test/sigkill_rain.c
@@ -0,0 +1,62 @@
+/* This test is not yet added to Makefile */
+
+#include <stddef.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+static const struct sockaddr sa;
+
+int main(int argc, char **argv)
+{
+ int loops;
+ int pid;
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ loops = 999;
+ if (argv[1])
+ loops = atoi(argv[1]);
+
+ while (--loops >= 0) {
+ pid = fork();
+ if (pid < 0) _exit(1);
+ if (!pid) {
+ /* child */
+ int child = getpid();
+
+ loops = 99;
+ while (--loops) {
+ pid = fork();
+ if (pid < 0) _exit(1);
+ if (!pid) {
+ /* grandchild: kill child */
+ kill(child, SIGKILL);
+ _exit(0);
+ }
+ /* Add various syscalls you want to test here.
+ * strace will decode them and suddenly find
+ * process disappearing.
+ * But leave at least one case "empty", so that
+ * "kill grandchild" happens quicker.
+ * This produces cases when strace can't even
+ * decode syscall number before process dies.
+ */
+ switch (loops & 1) {
+ case 0: /* empty */ break;
+ case 1: sendto(-1, "Hello cruel world", 17, 0, &sa, sizeof(sa)); break;
+ }
+ /* kill grandchild */
+ kill(pid, SIGKILL);
+ }
+ _exit(0);
+ }
+ /* parent */
+ wait(NULL);
+ }
+ return 0;
+}