1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
/**
* Version of same in parent directory using wait6
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "tests/sys_mman.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <sys/signal.h>
#include <unistd.h>
/** Lock an entire file exclusively.
*
* @return 1 upon success, 0 upon failure.
*/
static int lock_file(const int fd)
{
struct flock fl;
fl.l_type = F_WRLCK; /* exclusive lock */
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0; /* lock entire file */
fl.l_pid = 0;
return fcntl(fd, F_SETLK, &fl) >= 0;
}
static int open_lock_and_map(const char* const process_name,
const char* const filename)
{
int fd;
int flags;
fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0)
{
perror("open");
goto err1;
}
flags = fcntl(fd, F_GETFD);
assert(flags >= 0);
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
assert(0);
fprintf(stderr, "%s: about to lock file for writing.\n", process_name);
if (! lock_file(fd))
{
perror("fcntl");
goto err2;
}
fprintf(stderr, "%s: file locking attempt succeeded.\n", process_name);
if (mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0) == 0)
{
perror("mmap");
goto err2;
}
goto out;
err2:
close(fd);
err1:
out:
return fd;
}
int main(int argc, char *argv[])
{
int fd1;
int fd2;
int exitcode = 1;
char filename[256];
snprintf(filename, sizeof(filename), "/tmp/valgrind-file-locking-test.%ld",
(long) getpid());
unlink(filename);
if ((fd1 = open_lock_and_map("parent", filename)) >= 0)
{
pid_t fork_result;
fork_result = fork();
switch (fork_result)
{
case -1:
perror("fork");
break;
case 0:
/* child */
fd2 = open_lock_and_map("child", filename);
if (fd2 >= 0)
{
close(fd2);
}
exit(0);
break;
default:
/* parent */
{
int child_status;
int wait_result;
struct __wrusage wrusage;
siginfo_t info;
wait_result = wait6(P_PID, fork_result, &child_status, WEXITED, &wrusage, &info);
assert(wait_result >= 0);
}
}
}
close(fd1);
unlink(filename);
fprintf(stderr, "Test finished.\n");
return exitcode;
}
|