Checking for duplicate instances
Hello all.
I'm currently looking for the following trick to do in Posix C: a way to
test if there is another instance of the current program already running.
In my usual (LabWindows) API, I call the following function at the start of
the program's execution:
Status = CheckForDuplicateAppInstance (ACTIVATE_OTHER_INSTANCE,
&ThereIsAnother);
What is the Posix equivalent ?
I'd like to avoid doing "ps | grep" at the shell level and keep everything
in C.
Thanks.
--
Guillaume Dargaud
[url]http://www.gdargaud.net/[/url]
Re: Checking for duplicate instances
On Nov 6, 12:49*am, "Guillaume Dargaud"
<use_the_form_on_my_contact_p...@www.gdargaud.net> wrote:
[color=blue]
> I'm currently looking for the following trick to do in Posix C: a way to
> test if there is another instance of the current program already running.
>
> In my usual (LabWindows) API, I call the following function at the start of
> the program's execution:
> Status = CheckForDuplicateAppInstance (ACTIVATE_OTHER_INSTANCE,
> &ThereIsAnother);
>
> What is the Posix equivalent ?
> I'd like to avoid doing "ps | grep" at the shell level and keep everything
> in C.[/color]
There is no "one right way". The right way depends on your outer
problem. What would go wrong if two instances were to run? Why should
what Jack is doing affect what Jill is doing?
DS
Re: Checking for duplicate instances
> There is no "one right way". The right way depends on your outer[color=blue]
> problem. What would go wrong if two instances were to run? Why should
> what Jack is doing affect what Jill is doing?[/color]
OK, let's narrow down the issues:
it's on a single user (root) embedded system, but the prog can be started on
boot (by init.d) or manually from a serial console or an ssh login. In that
case I just want a way to tell the guy he forgot to kill the previous
instance.
The one issue I see is if I update the executable while one is running. The
new one has the some filename, although a different inode.
--
Guillaume Dargaud
[url]http://www.gdargaud.net/[/url]
Re: Checking for duplicate instances
"Guillaume Dargaud" <use_the_form_on_my_contact_page@www.gdargaud.net>
writes:
[color=blue][color=green]
>> There is no "one right way". The right way depends on your outer
>> problem. What would go wrong if two instances were to run? Why should
>> what Jack is doing affect what Jill is doing?[/color]
>
> OK, let's narrow down the issues:
> it's on a single user (root) embedded system, but the prog can be started on
> boot (by init.d) or manually from a serial console or an ssh login. In that
> case I just want a way to tell the guy he forgot to kill the previous
> instance.[/color]
A traditional method is this: create a file in /var/run called
myprog.pid and containing the program's PID. Install signal handlers
for common signals (SIGINT, SIGTERM, SIGHUP, etc) that remove the file.
When the program starts, if the file exists, and a process with that PID
is running (you can test this with kill(pid, 0)) then the program is
most likely already running; otherwise, it's probably not, and you can
create the file and continue.
There are ways this can go wrong, but they're not likely.
Another possible approach might be to have a lockfile in /var/lock or
something. Upon starting, you create the file if it doesn't exist, then
try to acquire an exclusive lock on it (using flock(fd, LOCK_EX |
LOCK_NB) for example). If you succeed then all is well; if you fail
then the program is already running. This is probably a bit more reliable.
[color=blue]
> The one issue I see is if I update the executable while one is running. The
> new one has the some filename, although a different inode.[/color]
Huh?
Re: Checking for duplicate instances
On Nov 6, 2:07*am, "Guillaume Dargaud"[color=blue]
> OK, let's narrow down the issues:
> it's on a single user (root) embedded system, but the prog can be startedon
> boot (by init.d) or manually from a serial console or an ssh login. In that
> case I just want a way to tell the guy he forgot to kill the previous
> instance.
> The one issue I see is if I update the executable while one is running. The
> new one has the some filename, although a different inode.[/color]
If it 'bind's a port, there's nothing special you need to do. The
second instance will fail to bind.
If it does not, the best solution is probably to have the program
acquire some kind of exclusive lock on a resource such that both
instances can't have the exclusive lock. Locking a PID file in a known
location is one way to do this.
DS
Re: Checking for duplicate instances
Nate Eldredge <nate@vulcan.lan> writes:[color=blue]
> "Guillaume Dargaud" <use_the_form_on_my_contact_page@www.gdargaud.net>
> writes:
>[color=green][color=darkred]
>>> There is no "one right way". The right way depends on your outer
>>> problem. What would go wrong if two instances were to run? Why should
>>> what Jack is doing affect what Jill is doing?[/color]
>>
>> OK, let's narrow down the issues:
>> it's on a single user (root) embedded system, but the prog can be started on
>> boot (by init.d) or manually from a serial console or an ssh login. In that
>> case I just want a way to tell the guy he forgot to kill the previous
>> instance.[/color]
>
> A traditional method is this: create a file in /var/run called
> myprog.pid and containing the program's PID. Install signal handlers
> for common signals (SIGINT, SIGTERM, SIGHUP, etc) that remove the file.
>
> When the program starts, if the file exists, and a process with that PID
> is running (you can test this with kill(pid, 0)) then the program is
> most likely already running; otherwise, it's probably not, and you can
> create the file and continue.
>
> There are ways this can go wrong, but they're not likely.[/color]
You never had to debug a postfix-installation where one of the
servers would not start after a reboot, because the pid stored in its
pid-file was low enough that usually, by the time the postfix start
script ran, there was already another process running with this pid,
have you?
That's already enough to convince someone whose main field of
experience is using Windows on the desktop that a reinstall of the OS
is required to 'fix' the problem.
Re: Checking for duplicate instances
> If it does not, the best solution is probably to have the program[color=blue]
> acquire some kind of exclusive lock on a resource such that both
> instances can't have the exclusive lock. Locking a PID file in a known
> location is one way to do this.[/color]
Thank you all for the detailed examples.
I use GPIO resources, but I'm not sure if they are exclusive. I'll test it
out and try to go that way.
--
Guillaume Dargaud
[url]http://www.gdargaud.net/[/url]
Re: Checking for duplicate instances
Is this a correct way to proceed ?
fd = open(DevicePath, O_RDWR | O_NONBLOCK);
struct flock lock;
err = fcntl(fd, F_GETFL, &lock);
lock.l_type=F_WRLCK;
err = fcntl(fd, F_SETFL, &lock);
if (err==0) ; // No lock on device, we can proceed
else exit(1); // Device locked (by other instance ?)
I'm not sure what other flags of flock I need to set.
--
Guillaume Dargaud
[url]http://www.gdargaud.net/[/url]
Re: Checking for duplicate instances
"Guillaume Dargaud" <use_the_form_on_my_contact_page@www.gdargaud.net>
writes:[color=blue]
> Is this a correct way to proceed ?
>
> fd = open(DevicePath, O_RDWR | O_NONBLOCK);
> struct flock lock;
> err = fcntl(fd, F_GETFL, &lock);
> lock.l_type=F_WRLCK;
> err = fcntl(fd, F_SETFL, &lock);
> if (err==0) ; // No lock on device, we can proceed
> else exit(1); // Device locked (by other instance ?)[/color]
No. An uncompiled example of how to use fcntl locking would be
struct flock lock;
int fd, rc;
fd = open("/path/to/file", O_RDWR);
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0;
rc = fcntl(fd, F_SETLK, &lock);
If the file is unlocked, rc will be 0 and the process will have
acquired an exlusive lock on it. Otherwise, rc will be -1 and errno
contain a 'suitable error code' (either EAGAIN or EACCESS).