mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-11 22:08:14 +00:00
(Rusty Russell, rusty@rustcorp.com.au) tdb uses fcntl locks and mmap, and some of the tests fail under valgrind. strace showed valgrind opening the tdb file, reading 1024 bytes, then closing it. This is not allowed: POSIX says if you open and close a file, all fcntl locks on it are dropped (insane, yes). Finally got around to hacking the source to track this down: di_notify_mmap is doing the damage. The simplest fix was to hand in an optional fd for it to use, then have it do pread. I had to fix your pread; surely this should seek back even if the platform doesn't have pread support? git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12224
69 lines
1.5 KiB
C
69 lines
1.5 KiB
C
|
|
/* Test program to demonstrate valgrind breaking fcntl locks during
|
|
* mmap. Feed it a r/w file, such as its own source code. */
|
|
|
|
/* See bug 280965. */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <err.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct flock fl;
|
|
const char *file = /* argv[1]; */
|
|
"mmap_fcntl_bug.c";
|
|
int fd, status;
|
|
|
|
if (!file)
|
|
errx(1, "Usage: %s <normal-file>", argv[0]);
|
|
|
|
fd = open(file, O_RDWR);
|
|
if (fd < 0)
|
|
err(1, "Opening %s", file);
|
|
|
|
fl.l_type = F_WRLCK;
|
|
fl.l_whence = SEEK_SET;
|
|
fl.l_start = 0;
|
|
fl.l_len = 1;
|
|
|
|
/* I'm assuming noone else tries to lock this! */
|
|
if (fcntl(fd, F_SETLK, &fl) != 0)
|
|
err(1, "Locking %s", file);
|
|
|
|
/* If under valgrind, mmap re-opens and closes file, screwing us */
|
|
if (mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0) == MAP_FAILED)
|
|
err(1, "mmap of %s", file);
|
|
|
|
switch (fork()) {
|
|
case 0:
|
|
/* Child. Lock should fail. */
|
|
if (fcntl(fd, F_SETLK, &fl) == 0)
|
|
exit(1);
|
|
exit(0);
|
|
case -1:
|
|
err(1, "Fork failed");
|
|
}
|
|
|
|
if (wait(&status) == -1)
|
|
err(1, "Child vanished?");
|
|
|
|
if (!WIFEXITED(status))
|
|
errx(1, "Child died with signal %i", WTERMSIG(status));
|
|
|
|
switch (WEXITSTATUS(status)) {
|
|
case 1:
|
|
errx(1, "Child got lock, we must have dropped it (TEST FAILED)");
|
|
case 0:
|
|
fprintf(stderr, "Child exited with zero (TEST PASSED).\n");
|
|
return 0;
|
|
default:
|
|
errx(1, "Child weird exit status %i", WEXITSTATUS(status));
|
|
}
|
|
}
|