My way to check if a progam is already running - Linux

This is a discussion on My way to check if a progam is already running - Linux ; On Jun 22, 7:48 am, Jan Panteltje wrote:
> Does not matter how many PIDs and whatever, if more then one, then there is
> an other instance running. abort.
> The check is made in main() before any threads ...

Re: My way to check if a progam is already running

On Jun 22, 7:48 am, Jan Panteltje wrote:
> Does not matter how many PIDs and whatever, if more then one, then there is
> an other instance running. abort.
> The check is made in main() before any threads etc.. are launched.
> it is really simple.
> Works for me, so due to the nature of computers and Turing machines, should
> work for you too.

What if two instances are started at about the same time. They both
run 'pidof' and find the other instance. They both then stop.

DS

Re: My way to check if a progam is already running

Jan Panteltje writes:
> On Fri, 22 Jun 2007 20:03:07 +0200 it happened Rainer Weikusat
> wrote in <87vedf989w.fsf@fever.mssgmbh.com>:
>>The problem is that two instances of the program which were started at
>>about the same time (in computer terms, not human terms) could both
>>read two pids from the pids file, because the second instance could
>>write the file with the two pids before the first has read the file
>>with the one pid.
>
> Then both would abort? and then user would have to press the button
> again.

Pretty inconvenient for user. If I press a button I expect application
to run.
>>An easy way to see this in action should be to insert a
>>'raise(SIGTSTP)' after the pclose, to start two instances of the program
>>and then continue them both. This isn't very likely to ever happen on
>>its own on a single-user system, though.
>
> Normally, as it is a user pressing a quick key, or a mouse click on an
> icon, I'd say there is too much time involved between actions for this
> to happen. Normal human response is about 200mS IIRC, click a mouse
> faster then that is very difficult I think.
> And even if you did, there is overhead, window manager, xmodmap,
> xbindkeys. X, the whole chain, looking through the path....

You don't know if user will run your application using a button. S/he
may run it using a shell script s/he wrote. And this script may
introduce bug that two instances are run.

Besides, it doesn't matter. The code you presented involves race
condition and you cannot deny it (well, you can -- I assume we both live
in free countries -- but you won't be right) and since it involves race
condition it has a bug. It may be so that this bug doesn't really
matter never less it is a bug and it's a bad programming practise to
leave it running/flying in your application.

Re: My way to check if a progam is already running

On a sunny day (Sat, 23 Jun 2007 11:52:54 +0200) it happened Michal Nazarewicz wrote in <87645fj8uh.fsf@erwin.mina86.com>:
>You don't know if user will run your application using a button.

I know, I am the user.
>condition it has a bug. It may be so that this bug doesn't really
>matter never less it is a bug and it's a bad programming practise to
>leave it running/flying in your application.

Re: My way to check if a progam is already running

On a sunny day (Sat, 23 Jun 2007 12:05:34 +0200) it happened Michal Nazarewicz wrote in <871wg3j89d.fsf@erwin.mina86.com>:
>With the above code I think it is not possible to start two instances in
>such a way that both will continue running. The worst case is that they
>both will abort. (It's still a bug.)
>
>I still don't see why you don't want to lock a file at the start and
>unlock it when program terminates. It's way simpler operation:

Yes, but then you have 2 GUI up for example, and then user selects a number
of entries (headers) in the second GUI (first one is hidden behing something),
and goes online to get the article bodies and THEN gets an error message when
the reader wants to start writing to the locked files.
Usually I mark about 50 to 100 entries, a lot of work for nothing.
It is better to prevent instance 2 from running at all.

Re: My way to check if a progam is already running

Jan Panteltje writes:
> On Sat, 23 Jun 2007 12:05:34 +0200 it happened Michal Nazarewicz
> wrote in <871wg3j89d.fsf@erwin.mina86.com>:
>
>>With the above code I think it is not possible to start two instances in
>>such a way that both will continue running. The worst case is that they
>>both will abort. (It's still a bug.)
>>
>>I still don't see why you don't want to lock a file at the start and
>>unlock it when program terminates. It's way simpler operation:
>
> Yes, but then you have 2 GUI up for example,

??? How locking a file lock differs from getting number of applications
with given name? Simply replace your checking routine with what I wrote
and you have the same functionality but more portable and without any
bugs.

Re: My way to check if a progam is already running

On 23 jun, 15:18, Michal Nazarewicz wrote:
> Jan Panteltje writes:
> > On Sat, 23 Jun 2007 12:05:34 +0200 it happened Michal Nazarewicz
> > wrote in <871wg3j89d....@erwin.mina86.com>:
>
> >>With the above code I think it is not possible to start two instances in
> >>such a way that both will continue running. The worst case is that they
> >>both will abort. (It's still a bug.)
>
> >>I still don't see why you don't want to lock a file at the start and
> >>unlock it when program terminates. It's way simpler operation:
>
> > Yes, but then you have 2 GUI up for example,
>
> ??? How locking a file lock differs from getting number of applications
> with given name? Simply replace your checking routine with what I wrote
> and you have the same functionality but more portable and without any
> bugs.

Maybe I do not understand you, but for example in this newsreader
there is not
just _one_ file, there are many (one for each newsgroup, one or more
for each posting, some for fonts, some for other purposes, some to
hold all groups,
some for indexes, for article headers, one for each article body, and
also these
files are created when needed (for example you subscribe to a group or
post a reply, edit a text, what not).
So it is not really possible to 'just lock at the start of the
program', the issue is
that no second program SHALL run, because if it does not run it
_CANNOT_ do things to files it should not do.

More unlike putting a lock on each inside door, just have one of the
gate.
Makes life easier if you live there.

Re: My way to check if a progam is already running

panteltje@yahoo.com writes:
> On 23 jun, 15:18, Michal Nazarewicz wrote:
>> Jan Panteltje writes:
>> > On Sat, 23 Jun 2007 12:05:34 +0200 it happened Michal Nazarewicz
>> > wrote in <871wg3j89d....@erwin.mina86.com>:
>>
>> >>With the above code I think it is not possible to start two instances in
>> >>such a way that both will continue running. The worst case is that they
>> >>both will abort. (It's still a bug.)
>>
>> >>I still don't see why you don't want to lock a file at the start and
>> >>unlock it when program terminates. It's way simpler operation:
>>
>> > Yes, but then you have 2 GUI up for example,
>>
>> ??? How locking a file lock differs from getting number of applications
>> with given name? Simply replace your checking routine with what I wrote
>> and you have the same functionality but more portable and without any
>> bugs.
>
> Maybe I do not understand you, but for example in this newsreader
> there is not
> just _one_ file, there are many (one for each newsgroup, one or more
> for each posting, some for fonts, some for other purposes, some to
> hold all groups,
> some for indexes, for article headers, one for each article body, and
> also these
> files are created when needed (for example you subscribe to a group or
> post a reply, edit a text, what not).

I'm not saying that you have to lock one of the data files, however
if it would be possible for two newsreader operate on the same data
files I think that would be the best option.

What I'm proposing is to create a lock file for example in a directory
with all the data files. That is, if you keep all the configuration and
data files in "~/.my-newsreader" you can create a file
"~/.my-newsreader/.lockfile" (using int fd = create(foo, 0600)) and then
lock it (using flock(fd, LOCK_EX)). If locking succeed (providing that
you are not using NFS) you're the only application if it fails there's
some application running already.

Re: My way to check if a progam is already running

On a sunny day (Sun, 24 Jun 2007 00:59:43 +0200) it happened Michal Nazarewicz wrote in <877ipuqnts.fsf@erwin.mina86.com>:
>I'm not saying that you have to lock one of the data files, however
>if it would be possible for two newsreader operate on the same data
>files I think that would be the best option.
>
>What I'm proposing is to create a lock file for example in a directory
>with all the data files. That is, if you keep all the configuration and
>data files in "~/.my-newsreader" you can create a file
>"~/.my-newsreader/.lockfile" (using int fd = create(foo, 0600)) and then
>lock it (using flock(fd, LOCK_EX)). If locking succeed (providing that
>you are not using NFS) you're the only application if it fails there's
>some application running already.

Yes, sorry, after posting that last night it hit me that that was what you
were suggesting, I thought you did mean lock every single file.
Yes yours clearly is the best solution, and I will have go at implementing that.
The main advantage I see is not the task switch issue, but now different
users are supported, my solution allowed one and only one instance to run.

I do still maintain that your fear of task switch messing up things were
ungrounded, as for example to start from GUI in my case (fvwm) needs
double click, no way are you doing 2 double clicks within a task switch,
same with key presses.....

Do you want to be mentioned in the code so if it does not work they can come
after you?

Re: My way to check if a progam is already running

Michal Nazarewicz writes:
>> Michal Nazarewicz writes:
>>> That's why you should use lock files, ie. you try to lock a file and on
>>> success you're the only instance.
>
> Rainer Weikusat writes:
>> A 'lock file' is something different from a 'file lock'.
>
> True. However you need one to use the other. That is you need to lock
> your lock file or otherwise there's a race condition. (Note that
> creating file with O_EXCL is also a way of locking a file.)

Note that 'creating the file with O_EXCL' yields exactly the problem
Jan was talking about in his post: The application terminates in a way
the person who wrote the code didn't think or care about, which leaves
a stale lockfile behind and if the code wasn't written to handle this
situation, someone needs to manually remove the lock file, silently
assuming that this someone at least knows about this possibility and
where to look for this file. The 'classic' cuplrits here would be
'Netscape and its direct sucessors'. If people try to be clever and
make this more complicated in the obvious way, namely, storing the pid in
the file and checking for existence of a process with this pid, the
problem gets actually worse: An issue I had to deal with last year was
that one of the processes making up the mailserver installation my
employer was using then wouldn't start after a power-cycle, ordered by
the 'technician on shift' because there was some "problem" and he it
no other idea of dealing with it. As it turned out to be, the pid
stored in the corresponding lock file was numerically small enough
that, by the time the process using the lock file did his kill(0,
...)-check, an unrelated process using this pid would usually already
be runnning. A problem like this would probably enough for a 'usually
competent certified as blubb'-technician to seriously consider
reinstalling the system from scratch, especially taking into account
that "something must be done quickly to get it running again". And I
wouldn't even blame him for that, because why should he have any clue
about the system call API of the OS?

Using some real file or record lock is a much better way, because that
is guaranteed to go away on its own if the lock holder terminates, no
matter what was causing this. It is still racy, though, because an
instance that is just starting up could be prevented from really
running by one that is just in the process of dying, but still holds
the lock.

Re: My way to check if a progam is already running

On a sunny day (Sun, 24 Jun 2007 10:00:14 GMT) it happened Jan Panteltje wrote in :

Seems to work:

// see man 3 lockf

#include

struct passwd *userinfo;
FILE *lockfile;

/* get user info */
userinfo = getpwuid(getuid() );

/* get home directory */
home_dir = strsave(userinfo -> pw_dir);

/* Locking code based on a suggestion by Michal Nazarewicz, but I use lockf(), not flock() */

----------------------------------------------------------------------------------------
Note:
Not all systems support lockfiles, so I added a define so it uses the old method if not.
Code tested with multiple users too.

Re: My way to check if a progam is already running

> On Sun, 24 Jun 2007 00:59:43 +0200 it happened Michal Nazarewicz
> wrote in <877ipuqnts.fsf@erwin.mina86.com>:
>
>>What I'm proposing is to create a lock file for example in a directory
>>with all the data files. That is, if you keep all the configuration and
>>data files in "~/.my-newsreader" you can create a file
>>"~/.my-newsreader/.lockfile" (using int fd = create(foo, 0600)) and then
>>lock it (using flock(fd, LOCK_EX)). If locking succeed (providing that
>>you are not using NFS) you're the only application if it fails there's
>>some application running already.

Jan Panteltje writes:
> Yes, sorry, after posting that last night it hit me that that was what
> you were suggesting, I thought you did mean lock every single file.
> Yes yours clearly is the best solution, and I will have go at
> implementing that. The main advantage I see is not the task switch
> issue, but now different users are supported, my solution allowed one
> and only one instance to run.

In fact, you can provide a switch for data directory and one user would
then be able to run several instances each running on different data
sets.
> I do still maintain that your fear of task switch messing up things were
> ungrounded, as for example to start from GUI in my case (fvwm) needs
> double click, no way are you doing 2 double clicks within a task switch,
> same with key presses.....

I'm not claiming it's likely to happen however it *is* a race condition
and race conditions *are* *bad*.
> Do you want to be mentioned in the code so if it does not work they can come
> after you?

Re: My way to check if a progam is already running

On a sunny day (Sun, 24 Jun 2007 17:48:50 +0200) it happened Michal Nazarewicz wrote in <87645dl5el.fsf@erwin.mina86.com>:
>I don't think you need two loops. From what I understood EAGAIN means
>that file is already locked (or otherwise cannot be locked):

Yes, you could be right, I would have to look at the lockf source to make sure.

Re: My way to check if a progam is already running

On a sunny day (Sun, 24 Jun 2007 17:48:50 +0200) it happened Michal Nazarewicz wrote in <87645dl5el.fsf@erwin.mina86.com>:
>I don't think you need two loops. From what I understood EAGAIN means
>that file is already locked (or otherwise cannot be locked):

I didn't claim it was wrong but that it wouldn't do anything useful.
Which it doesn't. The 'real test' is the lock(..., F_TLOCK in the
second loop and that will or will not succeed, no matter how many
times F_TEST succeeded or didn't succeed before.

Re: My way to check if a progam is already running

On a sunny day (Mon, 25 Jun 2007 13:57:55 +0200) it happened Rainer Weikusat wrote in <87bqf4b60s.fsf@fever.mssgmbh.com>:
>Jan Panteltje writes:
>> On a sunny day (Mon, 25 Jun 2007 10:30:28 +0200) it happened Rainer Weikusat
>> wrote in <87k5tsbfmj.fsf@fever.mssgmbh.com>:
>>
>>>Jan Panteltje writes:
>>>
>>>[...]
>>>
>>>
>>>> /* test if file is locked */
>>>> i = 0;
>>>> while(1)
>>>> {
>>>> a = lockf(fileno(lockfile), F_TEST, 0);
>>>> if(a != -1) break;
>>>>
>>>> if(errno != EAGAIN)
>>>> {
>>>> fprintf(stderr, "MyProgram: An other MyProgram is already running, aborting.\n");
>>>>
>>>> exit(1);
>>>> }
>>>>
>>>> i++;
>>>> if(i == 1000) // 10 S
>>>> {
>>>> fprintf(stderr, "MyProgram: timeout EAGAIN waiting for lockf() F_TEST, aborting.\n");
>>>>
>>>> exit(1);
>>>> }
>>>>
>>>> usleep(10000); // 10 ms
>>>> }
>>>
>>>This loop is totally useless, because by the time you do the second
>>>lockf call, the file may or may not be locked and it doesn't matter
>>>what another lockf call happening in the past returned.
>>
>> EAGAIN means test again, and I have tested this soft and forced the EAGAIN condition.
>> Unless (we still have to look at the lockf() source) EAGAIN is used
>> wrongly, the loop is correct.
>
>I didn't claim it was wrong but that it wouldn't do anything useful.
>Which it doesn't. The 'real test' is the lock(..., F_TLOCK in the
>second loop and that will or will not succeed, no matter how many
>times F_TEST succeeded or didn't succeed before.

If it did not succeed, but errno was EAGAIN then what would you do?
Ignore errno? This can be done.
The issue was that we are not sure if something happened that required
the test to run again.
That depends on the code of lockf().

As I did not write lockf() and am not in the mood to go find the source,
from this follows it is much earier to write your own OS and ppas.