Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

File locks for linux

I tried using temp files:

char *temp = tempnam(NULL, "myapp_");
printf("Tempname: %s", temp)     // Prints /tmp/myapp_random
while (1) { }

But when I check /tmp (while the app is still running), the myapp_random is not there!

As for using File Locks, I can't get a good grasp on it, I tried looking at <fcntl.h> but it seems to focus on locks in specified portions of a file. I just want to use the file entirely as a lock (which is why I prefer trying the temp file approach).

Any ideas?

like image 930
user657178 Avatar asked Feb 03 '23 17:02

user657178


1 Answers

tempnam doesn't create the file, it just gives you a filename that didn't exist at the time you called it.

You still have to create the file yourself and therefore still have the race condition that another process may sneak in and create it before you.

You don't actually want to use tempnam since that will give each process its own file name and they will be able to run concurrently. What you need is a fixed file name (like /tmp/myapp.lck for example) which each process opens and then attempts to flock.

You're better off with flock for a lock file, fcntl will give you a finer grain of locking (parts of files) but that's not really a requirement here.

The code would run something like this:

if ((mylockfd = open ("/tmp/myapp.lck", O_CREAT | O_RDWR, 0666)) < 0) {
    // error, couldn't open it.
    return;
}
if (flock (mylockfd, LOCK_EX | LOCK_NB) < 0) {
    // error, couldn't exclusive-lock it.
    return;
}
:
// Weave your magic here.
:
flock (mylockfd, LOCK_UN);

That probably needs some work but should be a good start. A more generalised solution would be something like:

int acquireLock (char *fileSpec) {
    int lockFd;

    if ((lockFd = open (fileSpec, O_CREAT | O_RDWR, 0666))  < 0)
        return -1;

    if (flock (mylockfd, LOCK_EX | LOCK_NB) < 0) {
        close (lockFd);
        return -1;
    }

    return lockFd;
}

void releaseLock (int lockFd) {
    flock (lockFd, LOCK_UN);
    close (lockFd);
}

// Calling code here.

int fd;
if ((fd = acquireLock ("/tmp/myapp.lck")) < 0) {
    fprintf (stderr, "Cannot get lock file.\n");
    return 1;
}

// Weave your magic here.

releaseLock (fd);
like image 191
paxdiablo Avatar answered Feb 05 '23 15:02

paxdiablo