9

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?

merlin2011
  • 71,677
  • 44
  • 195
  • 329
user657178
  • 213
  • 1
  • 3
  • 7
  • This looks like a duplicate of http://stackoverflow.com/questions/800730/c-c-how-to-tell-if-a-program-is-already-running – Richard Schneider May 31 '11 at 04:24
  • 1
    @Richard, that question was specifically for Windows. This one is almost certainly a UNIXy-type one since (1) `tempnam` was deprecated in VC2005, (2) the code references `/tmp/myapp_random` which is not really a Windows thing. – paxdiablo May 31 '11 at 05:48

1 Answers1

12

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);
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • A million thanks!! YAY :D the 0_CREAT | 0_RDWR, 0666 worked... I think before you only had 0_CREAT but this is exactly what I needed. Thanks a lot :) – user657178 May 31 '11 at 04:30
  • Is it safe to have the `close` after `flock(lockFd, LOCK_UN)`? Could this not lead to undefined behavior ? – cogle Oct 31 '18 at 23:22