books/apitue/sample-code/12/flock.c

92 lines
2.2 KiB
C
Raw Permalink Normal View History

2024-01-20 14:39:54 +00:00
/* This file is part of the sample code and exercises
* used by the class "Advanced Programming in the UNIX
* Environment" taught by Jan Schaumann
* <jschauma@netmeister.org> at Stevens Institute of
* Technology.
*
* This file is in the public domain.
*
* You don't have to, but if you feel like
* acknowledging where you got this code, you may
* reference me by name, email address, or point
* people to the course website:
* https://stevens.netmeister.org/631/
*/
/* This program illustrates the use of flock(2). Run two concurrent
* processes to show how a shared lock can be applied by both, but only
* one process can upgrade to an exclusive lock.
*
* Illustrate blocking and non-blocking modes: in blocking mode, we
* are avoiding the danger of a deadlock by the fact that upgrading a read
* lock releases that lock, allowing the second process to eventually get
* the exlusive lock. In non-blocking mode, we avoid a deadlock by
* explicitly releasing all locks and aborting after 10 tries.
*/
#include <sys/file.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void
progress() {
for (int i=0; i < 10; i++) {
/* Using write(2), because printf(3) is line-buffered. */
(void)write(STDOUT_FILENO, ".", 1);
sleep(1);
}
}
int
main(int argc, char **argv) {
int i, fd, flags;
(void)argv;
if ((fd = open("/tmp/1", O_CREAT|O_RDWR, 0644)) == -1) {
(void)fprintf(stderr, "Unable to open /tmp/1: %s", strerror(errno));
exit(EXIT_FAILURE);
/* NOTREACHED */
}
if (flock(fd, LOCK_SH) < 0) {
perror("flocking");
exit(EXIT_FAILURE);
/* NOTREACHED */
}
(void)printf("Shared lock established - sleeping for 10 seconds.\n");
progress();
(void)printf("\nNow trying to get an exclusive lock.\n");
flags = LOCK_EX;
if (argc > 1) {
flags |= LOCK_NB;
}
for (i=0; i < 10; i++) {
if (flock(fd, flags) < 0) {
(void)printf("Unable to get an exclusive lock.\n");
if (i==9) {
(void)printf("Giving up all locks.\n");
flock(fd, LOCK_UN);
exit(EXIT_FAILURE);
/* NOTREACHED */
}
sleep(1);
} else {
(void)printf("Exclusive lock established.\n");
break;
}
}
progress();
(void)printf("\n");
(void)close(fd);
exit(EXIT_SUCCESS);
}