Question

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.

Was it helpful?

Solution

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.

addenda: should check for failures

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top