In C programming, is there a way to achieve timeout on flock()?
Thanks.
#include <sys/file.h>
int flock(int fd, int operation);
In C programming, is there a way to achieve timeout on flock()?
Thanks.
#include <sys/file.h>
int flock(int fd, int operation);
You can use SIG_ALARM to do it. http://www.gnu.org/software/libc/manual/html_node/Setting-an-Alarm.html It is kind of tricky though, especially if you are dealing with multiple threads. You would have to make sure that your system delivers the sig alarm to the thread that set it always, and it might not be the case... in which case you would need to play with pthread_sigmask http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_sigmask.html to make sure that only your thread has the signal enabled... but what if 2 threads are blocking on flock at the same time? You will need to add some kind of mutex wrapper for that.
If you cannot use SIGALARM for some reason, your other option is busy waiting with LOCK_NB. Both of these options were already mentioned but here is an example with LOCK_NB:
#include <sys/file.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
int flock_with_timeout(int fd, int timeout) {
struct timespec wait_interval = { .tv_sec = 1, .tv_nsec = 0 }; // 1 sec
int wait_total = 0; // Total time spent in sleep
while (flock(fd, LOCK_EX | LOCK_NB) == -1) {
if (errno == EWOULDBLOCK) {
// File is locked by another process
if (wait_total >= timeout) { // If timeout is reached
printf("Timeout occurred while waiting to lock file\n");
return -1;
}
sleep(wait_interval.tv_sec);
wait_total += wait_interval.tv_sec;
} else {
perror("flock - failed to lock file");
return -1;
}
}
return 0;
}
You can use this function like so:
int main() {
int fd = open("file.txt", O_WRONLY | O_CREAT, 0640);
if (fd == -1) {
perror("open - failed to open file");
return 1;
}
if (flock_with_timeout(fd, 5) != 0) {
close(fd);
return 1;
}
printf("Got the lock\n");
/* ... you can work with the file here ... */
// Don't forget to unlock the file
if (flock(fd, LOCK_UN) == -1) {
perror("flock - failed to unlock file");
close(fd);
return 1;
}
close(fd);
return 0;
}
Note 1: If you are exiting main() and thus terminating the program, you don't need to unlock, nor close the file handle. This will be done automatically.
Note 2: close() may also fail and should be error-checked.
Note 3: As @MK already mentioned, the problem with LOCK_NB is that you will be getting the lock with a delay up to your sleep time which may not be acceptable. In the example we are sleeping for 1 second.