srikrishnan has asked for the wisdom of the Perl Monks concerning the following question:

Hi Friends,

I have written a small Tool in perl. I have used Tk for Graphical user interface. Sometimes accidentally we clicked twice the tool. So it picks up the same file and clashes. In order to avoid this, I try to check at the time of clicking the tool whether it is running already or not? I want to exit if the tool is already running.

Is this possible how can I achieve this?

Please help me

Thanks in Advance

Srikrishnan

Replies are listed 'Best First'.
Re: how to exit if tool is already running
by sflitman (Hermit) on Aug 12, 2010 at 05:58 UTC
    Check out the excellent CPAN module Sys::RunAlone, it should help fix this problem. It cleverly locks your scripts DATA handle to prevent another invocation of the same script doing so. It's cross-Unix, but you'd need something fancier on Windows.

    HTH,
    SSF

      Considering flocking the data handle only takes a single line, there isn't much to gain from using a module (the module does more, but the OP doesn't need that). After ending the script with __DATA__ (or __END__), just add:
      flock DATA, 6 or die "Duplicate instance";
      Or use the Fnctl module and use LOCK_EX|LOCK_NB instead of 6.
Re: how to exit if tool is already running
by cdarke (Prior) on Aug 12, 2010 at 11:59 UTC
    The Windows way to do it, rather than using a file lock, is to use a named Mutex. This is how many programs achieve this on Windows. See Win32::Mutex, which I think is bundled with ActiveState Perl.
Re: how to exit if tool is already running
by wwe (Friar) on Aug 12, 2010 at 08:34 UTC
    The easiest is to check for the existence of a special file on a start-up if the file not exists create a temporary file and delete this file after the script has finished. Then you can decide to exit the script if the file already exists. This would be a problem if the first started script crashes without deleting a file. Maybe you want to do a double check if the file exists and the process perl.exe is running. This technique is pretty common for *nix utilities to prevent double execution as it is easy to implement but you should be aware this is not very reliable.

    UPDATE: maybe you want to read about File locking and implement this in your script as you mentioned the problem comes from parallel access to the same file.

      The easiest is to check for the existence of a special file on a start-up if the file not exists create a temporary file and delete this file after the script has finished.
      That's not easy at all. In fact, if you do it as you state, you have a solution with a race condition, as you aren't doing the "check if a file exists; create it otherwise" atomically. Furthermore, you have a problem if the program dies and doesn't get the chance to clean up the special file. Or if something else removes the file.
        JavaFan, I know we have had this discussion before, but the question says:
        I have written a small Tool in perl. ... Sometimes accidentally we clicked twice the tool. (emphasis mine)
        Given this, the complaint about an atomic procedure seems somewhat pedantic for a small (probably Q&D) tool.
        Furthermore, you have a problem if the program dies and doesn't get the chance to clean up the special file.
        Can be handled by either an exit handler or checking to see if the program is already running.
        Or if something else removes the file.
        Write and/or exclusive locks handle this.

        Even if it is not how you would do it (possibly for a full blown application), it may well fit the bill for this task.

Re: how to exit if tool is already running
by dasgar (Priest) on Aug 12, 2010 at 06:10 UTC

    I think that it should be possible to determine if a process with that name is already running, although I've never tried doing that in code before. If you're running on Windows, you might want to check out http://roth.net/ to see if they have a Win32 module that help you out.

    As for doing this in *nix, don't know. If there are no Perl modules that do this, there may be shell/system commands that can help. However, I know just enough to be dangerous in the *nix environment. That means I know how to run the rm command and can get into vi to modify files.

      Hi All,

      Thanks for your response

      Sorry, I forgot to mention that I am using perl within Windows XP OS

      Thanks

      Srikrishnan

Re: how to exit if tool is already running
by zentara (Cardinal) on Aug 12, 2010 at 14:08 UTC
    Here is an old brute force method, that relies on the $0 name of the script in the process table. Works on linux only.
    #!/usr/bin/perl -w #just run it. The first time it starts the daemon. If you try to start # it a second time, it gives an error msg. Run it with any # commandline argument, #like "k" will kill all instances of the script use strict; use IO::Handle; use Proc::ProcessTable; use Proc::Daemon; my $t1 = new Proc::ProcessTable; my @pids; my $pid; foreach my $p (@{$t1->table}){ if($p->cmndline =~ /apache-monitor/){ $pid = $p->pid; #print "$pid\n"; push(@pids,$pid); #unless $pid == $$; } } ################################################### if (exists $ARGV[0]) { foreach $pid (@pids){ print "killing pid $pid\n"; kill 9,$pid; } } #################################################### if ($#pids > 0) { print "@pids already running!\n"; exit; } #################################################### Proc::Daemon::Init; #open(LOG,">>/var/log/apache-monitor.log") or die $!; #when run as roo +t open(LOG,">>/tmp/apache-monitor.log") or die $!; #for testing while (1){ my $ok =0; my $t = new Proc::ProcessTable; foreach my $p (@{$t->table}){ if($p->cmndline =~ /\/usr\/sbin\/httpd/){ print LOG time(),' ',$p->cmndline," already running!\n"; $ok=1;last; } } if ($ok == 0) {print LOG time(),' ',"failed!\n";} LOG->flush; sleep(15); }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku

      Hi,

      I have checked "win32::Mutex". But frankly said I cant understand how to use that for my purpose. Documentation is not userfriendly. If anybody have patience, please give me some sample code for my purpose, it would be very helpful.

      Thanks in Advance,

      Srikrishnan