Files
ftmemsim-valgrind/none/tests/mmap_fcntl_bug.c
Philippe Waroquiers f05d0d0969 patch fixing 297991: mmap changing a file descriptor current position
Bug caused by the following problem:
for each mmap, Valgrind reads the 1st 1024 bytes to detect
if this is an mmap-ed file containing debug info to decode.

Reading this 1Kb is done with VG_(pread). VG_(pread) should be
the equivalent of syscall pread but on linux, it is implemented as
a seek+read. 

The patch implements VG_(pread) in terms of the underlying pread syscall.

Test mmap_fcntl_bug.c completed to also verify the fd current position
before and after the mmap. 

tested on linux x86/amd64/ppc32/ppc64/s390.
(not tested on Darwin)
(manually tested on arm-android)



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12504
2012-04-13 23:07:29 +00:00

79 lines
2.0 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;
off_t initial;
if (!file)
errx(1, "Usage: %s <normal-file>", argv[0]);
fd = open(file, O_RDWR);
if (fd < 0)
err(1, "Opening %s", file);
// reproduce bug 297991: mmap interferes with fd position
initial = lseek(fd, 123, SEEK_SET);
if (123 != initial)
err(1, "initial off_t differs from 123 (TEST FAILED)");
if (lseek(fd, 0, SEEK_CUR) != 123)
err(1, "zero offset from initial differs from 123 (TEST FAILED)");
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);
if (lseek(fd, 0, SEEK_CUR) != 123)
errx(1, "zero offset from initial after mmap differs from 123 (TEST FAILED)");
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));
}
}