#define _GNU_SOURCE #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #define FNAME "kill-locks.tmp" #define BUFSIZE 16384 #define DEATHSIG SIGINT void sighandler(int signum) { if (0) signum = 0; } int main() { int successcount = 0; struct sigaction sa; sigset_t blockset, origset, waitset; /**/ sa.sa_handler = &sighandler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGUSR1, &sa, NULL) == -1) perror("sigaction(SIGUSR1)"), exit(1); if (sigaction(SIGCHLD, &sa, NULL) == -1) perror("sigaction(SIGCHLD)"), exit(1); sigemptyset(&blockset); sigaddset(&blockset, SIGUSR1); sigaddset(&blockset, SIGCHLD); if (sigprocmask(SIG_BLOCK, &blockset, &origset) == -1) perror("sigprocmask"), exit(1); waitset = origset; sigdelset(&waitset, SIGUSR1); sigdelset(&waitset, SIGCHLD); sigaddset(&waitset, DEATHSIG); while (1) { pid_t childpid = fork(); int status; /**/ if (childpid == (pid_t) -1) perror("fork()"), exit(1); if (childpid == 0) { /* Child */ int fd; struct flock lck; char buf[BUFSIZE]; /**/ if (sigprocmask(SIG_SETMASK, &origset, NULL) == -1) perror("[child] sigprocmask"), exit(1); fd = open(FNAME, O_RDWR|O_CREAT, 0666); if (fd == -1) perror("[child] open()"), exit(1); lck.l_type = F_WRLCK; lck.l_whence = SEEK_SET; lck.l_start = (off_t)0; lck.l_len = (off_t)0; if (fcntl(fd, F_SETLK, &lck) == -1) perror("[child] fcntl(F_SETLK)"), exit(1); memset(buf, 0, sizeof(buf)); kill(getppid(), SIGUSR1); while(1) write(fd, buf, sizeof(buf)); } if ( ! (sigsuspend(&waitset) == -1 && errno == EINTR)) perror("sigsuspend"), exit(1); usleep(rand()%1000); kill(childpid, DEATHSIG); if (waitpid(childpid, &status, 0) != childpid) perror("waitpid"), exit(1); if ( ! (WIFSIGNALED(status) && WTERMSIG(status) == DEATHSIG)) { fprintf(stderr, "unexpected status from child %08X\n" "successful locking attempts: %d\n", status, successcount); exit(1); } ++successcount; } }