mmap_fcntl_bug.c revision 8f943afc22a6a683b78271836c8ddc462b4824a9
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
16int 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