Re: Process Already Running
by Joost (Canon) on Sep 13, 2007 at 16:26 UTC
|
That code doesn't work as described. It returns true if there are any programs running that match.
anyway.
Since you're not locking, you've just created a race condition: if two processes are started at around the same time, they will detect each other and both exit (provided the process name they're testing is static and their own - if the process name changes for some reason, it's possible that they won't detect each other and both will continue running).
| [reply] [Watch: Dir/Any] |
|
Thanks. I appreciate your reply. In my particular application, the three situations that you mention: 1) match multiple instances 2) both exit 3) neither exit if name has changed, are acceptable or even desirable. I forgot to mention that my scripts will be scheduled by cron to run every minute, but sometimes they will take more than one minute to complete. If one newly starting instance exits unnecessarily, it is ok since it will run again the next minute.
What would not be acceptable though, would be if they both have the same name but, for some reason neither of them exit. I just figured that it might be less messy than having to deal with lock files, which if I understand the previous threads on the subject, can also have a race condition.
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by erix (Prior) on Sep 13, 2007 at 16:27 UTC
|
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by andyford (Curate) on Sep 13, 2007 at 16:20 UTC
|
One problem is that you can have other processes that match that aren't the one you're looking for. For example, say your editing a program in vi at the same time that you're trying to see if that program is running. Then your grep might erroneously return an unwanted positive.
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by fmerges (Chaplain) on Sep 13, 2007 at 16:53 UTC
|
Hi,
Aside, I normally use File::Pid in my own written programs.
Regards,
fmerges at irc.freenode.net
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by shmem (Chancellor) on Sep 13, 2007 at 21:01 UTC
|
A quick search on 'flock', author 'merlyn' turns up •Re: Checking for multiple instances.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [Watch: Dir/Any] |
|
Thanks, shmem! That tip from the venerable merlyn works very nicely indeed!!!
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by andreas1234567 (Vicar) on Sep 13, 2007 at 17:48 UTC
|
| [reply] [Watch: Dir/Any] |
Re: Process Already Running
by Anno (Deacon) on Sep 13, 2007 at 17:52 UTC
|
A PID-based approach to process exclusion suffers from the possibility of PID re-use. Also, there is usually no atomic way of checking the pid *and* registering it. That doesn't mean the approach can't be used in practice, but there is a small probability of malfunction.
A safe approach can be based on file locking (flock), which is *meant* to guarantee exclusive access. The following code shows how that can be done in a Unix-ish environment. I'm sure there is already a module on CPAN (or two) that does this in a more portable way, but I couldn't find it in a hurry.
#!/usr/local/bin/perl
use strict; use warnings; $| = 1;
use Fcntl qw( :flock);
my $name = 'ttt'; # process name
my $pid_file = "/var/run/$name.pid";
open my $pid_handle, '+<', $pid_file or die "Can't access '$pid_file':
+ $!";
flock $pid_handle, LOCK_EX | LOCK_NB or die "Process $name is still ac
+tive";
truncate $pid_handle, 0 or die "Truncating '$pid_file' failed: $!";
print $pid_handle "$$\n";
# Normal processing starts here
#
# ...
sleep 10; # for testing
Update: I forgot to mention that the file /var/run/ttt.pid must be pre-created and given ownership and permissions so that the user that runs the process can write it.
Anno | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Thanks for your suggestion. I must have fallen out of a tree and hit my head (or maybe I'm always this stupid). I just realized that the code in my original post would always return TRUE (script already running) because the script itself is, of course, already in the Linux process list when it checks to see if a script of it's same name is already running. Duh!!
I'm not yet very familiar with Unix-ish systems and am not familiar with PIDs. In your sample code above, why did you open the pid file with +< (is this read-write but don't create?)? And what is the purpose for writing the Perl Process ID $$ to the file? Please help me understand how that is used?
| [reply] [Watch: Dir/Any] |
|
Heh, I didn't even notice the bug in your proposed scheme.
In your sample code above, why did you open the pid file with +< (is this read-write but don't create?)?
First off, I don't want to clobber the file before I've made sure I'm allowed to run. That's why plain write access won't do. Write access is required because many systems (foolishly, imo) forbid an exclusive lock on a file that's only open for reading. So even if I didn't intend to write my PID into the file (which is inessential, see below), simple read access would break in some places.
And what is the purpose for writing the Perl Process ID $$ to the file? Please help me understand how that is used?
That is absolutely inessential and not used at all. The locking scheme needs a file, unique to the specific program, that can be exclusively locked by the process. I have chosen a convention that is common in Unix systems, associating a process named ttt with a file /var/run/ttt.pid. As the name implies, it is commonly used to store the PID of the running process, and so I've done the same. The locking mechanism would also work without writing anything to the file, or with any other file for that matter.
I forgot to mention (but will update) that you would have to pre-create the pid file /var/run/ttt.pid (once), and give it ownership and permissions that allow the process write access. A real program should probably explain that in an error message if the file is not found.
Anno
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|