I do unlock and then close. One process appends records ABCDEFGHIJ. Another process reads the same file and writes ZZZZ. Normal file should be ZZZZ ABCDEFGHIJ
But only once I have seen the following: ZZZZEFGHIJ So the record ABCDEFGHIJ is damaged with ZZZZ.
It seems my locking does not work. But I tested it. One process really waiting for another. Can another process write to the file between open and lock? Or between unlock and close?
The code is below
int MyOpenWrite(char *name,int flags) {
int fd
fd = open(name,flags,S_IREAD|S_IWRITE|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
LockFile(fd);
return fd;
}
int WriteFile(char *name, char *data) {
...
fd = MyOpenWrite(fullName,O_CREAT|O_WRONLY|O_TRUNC);
write(fd,data,strlen(data));
UnLockFile(fd);
close(fd);
}
int ReadFile(char *name, char *data, int maxLength) {
fd = open(name,O_RDONLY);
LockFile(fd);
...
UnLockFile(fd);
close(fd);
}
int AppendFile(char *name, char *data) {
fd = MyOpenWrite(fullName,O_WRONLY|O_APPEND);
...
len=write(fd,data,strlen(data));
UnLockFile(fd);
close(fd);
}
int LockFile(int fd) {
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
return fcntl(fd,F_SETLKW,&lock);
}
int UnLockFile(int fd) {
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
return fcntl(fd,F_SETLKW,&lock);
}
I tried close(fd) the UnLock(fd). It seems it works. But there is a delay between open and lock anyway. Thanks.
As long as you don't write(2)
to a file (after the unlocking), it does not matter if you unlock it first or close(2)
it first.
However, close(2)
-ing a file would unlock it (at least if no other process share the same opened file descriptor).
See fcntl(2) which says
As well as being removed by an explicit F_UNLCK, record locks are automatically released when the process terminates or if it closes any file descriptor referring to a file on which locks are held.
Notice that your code is missing error checking. Almost every library function or syscall, in particular fcntl
, read
, write
, could fail (and set errno
to be displayed by e.g. perror
or strerror(errno)
in some log or print). You don't check the success or failure of fcntl
in your LockFile
or UnlockFile
functions, and you don't check neither in the caller.