Home | History | Annotate | Download | only in tests
      1 
      2 /* Test program to demonstrate valgrind breaking fcntl locks during
      3  * mmap.  Feed it a r/w file, such as its own source code. */
      4 
      5 /* See bug 280965. */
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <unistd.h>
     10 #include <fcntl.h>
     11 #include <sys/mman.h>
     12 #include <sys/types.h>
     13 #include <sys/wait.h>
     14 #include <err.h>
     15 
     16 int main(int argc, char *argv[])
     17 {
     18 	struct flock fl;
     19 	const char *file = /* argv[1]; */
     20 			   "mmap_fcntl_bug.c";
     21 	int fd, status;
     22 
     23 	if (!file)
     24 		errx(1, "Usage: %s <normal-file>", argv[0]);
     25 
     26 	fd = open(file, O_RDWR);
     27 	if (fd < 0)
     28 		err(1, "Opening %s", file);
     29 
     30 	fl.l_type = F_WRLCK;
     31 	fl.l_whence = SEEK_SET;
     32 	fl.l_start = 0;
     33 	fl.l_len = 1;
     34 
     35 	/* I'm assuming noone else tries to lock this! */
     36 	if (fcntl(fd, F_SETLK, &fl) != 0)
     37 		err(1, "Locking %s", file);
     38 
     39 	/* If under valgrind, mmap re-opens and closes file, screwing us */
     40 	if (mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0) == MAP_FAILED)
     41 		err(1, "mmap of %s", file);
     42 
     43 	switch (fork()) {
     44 	case 0:
     45 		/* Child.  Lock should fail. */
     46 		if (fcntl(fd, F_SETLK, &fl) == 0)
     47 			exit(1);
     48 		exit(0);
     49 	case -1:
     50 		err(1, "Fork failed");
     51 	}
     52 
     53 	if (wait(&status) == -1)
     54 		 err(1, "Child vanished?");
     55 
     56 	if (!WIFEXITED(status))
     57 		errx(1, "Child died with signal %i", WTERMSIG(status));
     58 
     59 	switch (WEXITSTATUS(status)) {
     60 	case 1:
     61 		errx(1, "Child got lock, we must have dropped it (TEST FAILED)");
     62 	case 0:
     63 		fprintf(stderr, "Child exited with zero (TEST PASSED).\n");
     64 		return 0;
     65 	default:
     66 		errx(1, "Child weird exit status %i", WEXITSTATUS(status));
     67 	}
     68 }
     69