|
Home > Archive > Unix Programming > June 2006 > fcntl() file locking issues
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
fcntl() file locking issues
|
|
| cgorac@gmail.com 2006-06-20, 1:24 pm |
| Could anyone point what's wrong with following locking code? After
compiling program, symbolic links "writer" and "reader" should be
created to executable, and then program should be launched first trough
name "writer" and then, within 10 seconds, trough name "reader".
Program "writer" is creating file, then locking it as a whole for
writing, then writing 4 bytes in file, then releasing the lock and
finally sleeping for 10 seconds in order to make possible to launch
"reader" program. This program is in turn locking whole file for
reading, then reading 4 bytes from file and printing this value to
standard output, and finally releasing the lock. The problem is,
"reader" program is blocked while trying to get read lock, until
"writer" program exited (or more precisely, until file descriptor
"fdout" used within "writer" program closed implicitly or explicitly,
in which case of course all related locks are relased). Added code to
get offending lock is printing that first program is still holding
write lock for whole contents of file.
Note that numerous variations are tried, including fsync()-ing after
writing to file from "writer" program, then locking explicitly for 4
bytes from start of the file instead of locking of whole file contents
(of course, in that case file with 4 bytes was actually created before
launching programs) etc. Note also that described behavior is observed
on both GNU/Linux (2.6.15.7 kernel, Slackware 10.2 distribution), as
well as on NetBSD 3.0.
Thanks.
/* --- */
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define FILENAME "test.txt"
int
main(int argc, char **argv)
{
if (strstr(argv[0], "writer") != NULL) {
int fdout;
struct flock lock;
int x;
fdout =
open(FILENAME, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
assert(fdout >= 0);
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 4;
fprintf(stderr, "writer: trying to acquire write lock\n");
assert(fcntl(fdout, F_SETLKW, &lock) == 0);
fprintf(stderr, "writer: acquired write lock\n");
x = 42;
write(fdout, &x, sizeof(int));
lock.l_type = F_UNLCK;
fprintf(stderr, "writer: trying to release write lock\n");
assert(fcntl(fdout, F_UNLCK, &lock) == 0);
fprintf(stderr, "writer: released write lock\n");
} else if (strstr(argv[0], "reader") != NULL) {
int fdin;
struct flock lock;
int x;
fdin = open(FILENAME, O_RDONLY);
assert(fdin >= 0);
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
assert(fcntl(fdin, F_GETLK, &lock) == 0);
if (lock.l_type != F_UNLCK) {
fprintf(stderr, "PROBLEM: %d %d %d %d %d\n",
lock.l_type, lock.l_whence, lock.l_start,
lock.l_len, lock.l_pid);
}
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
fprintf(stderr, "reader: trying to acquire read lock\n");
assert(fcntl(fdin, F_SETLKW, &lock) == 0);
fprintf(stderr, "reader: acquired read lock\n");
read(fdin, &x, sizeof(int));
fprintf(stderr, "%d\n", x);
lock.l_type = F_UNLCK;
fprintf(stderr, "reader: trying to release read lock\n");
assert(fcntl(fdin, F_UNLCK, &lock) == 0);
fprintf(stderr, "reader: released read lock\n");
}
sleep(10);
return 0;
}
| |
| davids@webmaster.com 2006-06-20, 7:25 pm |
|
cgorac@gmail.com wrote:
> Could anyone point what's wrong with following locking code?
> lock.l_type = F_WRLCK;
> lock.l_whence = SEEK_SET;
> lock.l_start = 0;
> lock.l_len = 4;
>
> fprintf(stderr, "writer: trying to acquire write lock\n");
> assert(fcntl(fdout, F_SETLKW, &lock) == 0);
> fprintf(stderr, "writer: acquired write lock\n");
>
> x = 42;
> write(fdout, &x, sizeof(int));
>
> lock.l_type = F_UNLCK;
Does this release the same lock it places? (Hint: what does SEEK_SET
mean?)
DS
| |
| cgorac@gmail.com 2006-06-21, 7:38 am |
| davids@webmaster.com wrote:
> cgorac@gmail.com wrote:
>
>
> Does this release the same lock it places? (Hint: what does SEEK_SET
> mean?)
>
> DS
I think it should release exactly the same lock, because SEEK_SET means
"start of the file". Am I wrong here?
Note also that assignment "lock.l_len = 4" should actually read
"lock.l_len = 0" - obviously after trying multiple variations I
mentioned in previous message I haven't reverted this assignment to its
initial form; but this doesn't change anything, for this version it is
only necessary to have preexisting "test.txt" file of 4 bytes length,
and locking problem is still there.
Thanks.
| |
| cgorac@gmail.com 2006-06-21, 7:38 am |
| cgorac@gmail.com wrote:
> Could anyone point what's wrong with following locking code?
>
> [ ... ]
>
Ok, got it: I used following command to unlock:
fcntl(fdin, F_UNLCK, &lock)
where it should be used:
fcntl(fdin, F_SETLKW, &lock)
So command actually executed on Linux was F_SETFD...
Thanks.
| |
| davids@webmaster.com 2006-06-22, 1:27 am |
|
davids@webmaster.com wrote:
> Does this release the same lock it places? (Hint: what does SEEK_SET
> mean?)
Sorry. Right problem, wrong hint.
DS
|
|
|
|
|