in reply to Abort if instance already running?

In such cases, I typically use a lock file, typically /var/run/name-of-program. When starting the program, create the file if it doesn't exist (using sysopen), then try to get a lock (nonblocking). If the process can get the lock, it knows it's the only instance running. If it cannot get the lock, another instance is running, and it exits.

It's a technique simple enough that I can't be bothered to look for a CPAN solution. And it can easily be implemented in a different language as well.

Replies are listed 'Best First'.
Re^2: Abort if instance already running?
by Marshall (Canon) on Jan 06, 2009 at 00:54 UTC
    Excellent approach and very standard. I would also think that the poster would want to install a signal handler(s) to release appropriate locks if the program dies, get's a CTL-C or whatever. Something like this:
    $SIG{'INT'} = \&release_lock; $SIG{'QUIT'} = \&release_lock; $SIG{'PIPE'} = \&release_lock; #maybe too? sub release_lock{ #...do what you can here... }

    The basic idea is not to leave locks around if your program abends. The lock strategy is simple, works well, and can be implemented in many languages on many O/s'es (some easier than others)..just remember to clean up if "bad things" happen to your program and the normal "release lock" code doesn't execute.

    The lock system is cooperative, meaning that everybody has to know what is going on and cooperate. It is possible to write a file that is "locked" for exclusive access. A file lock is more like an advisory thing and the programs that use it have to "play by the rules".

      I think the various "nit-picky details" of using file locking like this may be a good reason to stick with the pid-file idea explained in the initial reply -- assuming of course that the goal is to make sure only one instance of a program is running on the same host where you would be trying to start a new instance.

      If for some reason there are different hosts that share a given disk and might try to start instances of this process, but only one host at a time may run the one instance of the process, then you'd have to complicate the pid-file approach somewhat, and file locking might be easier/better overall (assuming it works reasonably well on your shared file system... YMMV).

        With Perl, there is always more than one way to do things! There is always a YMMV aspect!

        In the spirit of trying to be helpful, I wrote some simple code that I tested on my Windows machine. Attached below. I think the poster has a couple of solid ideas to work from and can decide what is best for what is likely a complex situation, of which we've only been given a part. It could also be that sometimes method A is best and sometimes method B is best. Sometimes method C is just fine even though it fails 1 of 100,000 times. The below is just an idea of how to implement one of many suggestions.

        #!/usr/bin/perl - w use strict; # test case on ActivePerl 5.10 under WinXP $|++; #turns off stdout buffering #good for testing but a big performance #penalty use Fcntl qw (:flock); $SIG{INT} = \&release_lock; $SIG{QUIT} = \&release_lock; my $lock_file = "$0.lck"; #this next open will succeed if you have w permission... #even if you you don't have the lock yet or lock file #doesn't exist yet.. open LOCKFILE, ">>$lock_file" || die "Cannot open $lock_file"; my $got_lock =flock(LOCKFILE, LOCK_EX | LOCK_NB); if ($got_lock) { print "lock acquired\n"; foreach (1..10) { print "Locked..doing something..$_ seconds\n"; sleep(1); } } else { print STDERR "could not acquire lock\n"; exit(1); } print "Finished...Normal Exit, releasing lock\n"; close LOCKFILE || die "Cannot close $lock_file"; unlink $lock_file || die "Internal program error"; exit(0); #not needed but this is normal close sub release_lock { print STDERR "Abnormal exit...releasing lock\n"; close LOCKFILE || die "Cannot close $lock_file"; unlink $lock_file || die "Internal program error"; exit(2); }
        Even without multiple hosts, also knowing the lockfile technique is worthwhile as it is more easily adaptable to represent other assets. That a lockfile must be cleaned up is an advantage in that situation. The ephemeral (crash) and expensive (proc-table) nature of a process work against you.

        That the process is both the contender and the symbol of contention hinders splitting out functionality into a separate administrative program.

        Under linux /var/lock is the place for lockfiles.

        Be well,
        rir

      just remember to clean up if "bad things" happen to your program and the normal "release lock" code doesn't execute.
      Needlessly complicated! I never work on an OS where a process that no longer exists continues to hold a lock on a file. On any Unix system I know of, if a program exits (be it normally, with a signal or by an error), all locks are released.

      You may need an explicit release of the lock if your program forks or execs, and you don't want the children or the new program to hold the lock.