mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
79 lines
2.0 KiB
C
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 no one 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));
|
|
}
|
|
}
|