mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
130 lines
2.4 KiB
C
130 lines
2.4 KiB
C
/** Test program for POSIX advisory record locking. See also #164669
|
|
* (http://bugs.kde.org/show_bug.cgi?id=164669).
|
|
* See also http://www.opengroup.org/onlinepubs/007908799/xsh/fcntl.html.
|
|
*/
|
|
|
|
|
|
#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 <unistd.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;
|
|
|
|
wait_result = wait4(fork_result, &child_status, 0, 0);
|
|
assert(wait_result >= 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
close(fd1);
|
|
|
|
unlink(filename);
|
|
|
|
fprintf(stderr, "Test finished.\n");
|
|
|
|
return exitcode;
|
|
}
|