Re: How do I ensure only one version of my executable is running
"David Ching" <dc@remove-this.dcsoft.com> wrote in message
news:SOjIh.301$JZ3.39@newssvr13.news.prodigy.net...
There is no more synchronization problem here than your usage of creating
a mutex. Both have the issue where it is possible for 2 instances to be
simultaneously started, check for the mutex, see it's not there, and
create it at the same time. This case is rightfully ignored because of
the vitual impossibility of starting 2 instances of an .exe that close
together.
After looking at your code in more detail, I see that it is in fact NOT
possible to have a race condition, since even if both instances called
CreateMutex() simultaneously, only one instance would succeed. So, kudos,
your mutex solution does not have a race condition.
But the shared data segment solution can also be coded that way. If you
have a BOOL g_bAppIsRunning variable, you can use
InterlockedCompareExchange() to test and assign this to TRUE, in a
thread-safe manner. This then allows the shared data segment to replace the
mutex with no disadvantage.
Now for using the shared data segment to pass data (e.g. command-line)
between instances (assuming it is permissible to have multiple instances
running simultaneously). Well, I think you are right some thread safety
issues with this. The command-line storage needs to be protected somehow,
although I'm not sure why you say a mutex will not work for this. So
perhaps Mr. Naughter's method should not be discarded so quickly, as Tom
pointed out.
Finally, in your article, you say, "After you read the section on Race
Conditions you may see that this code has a race condition. If the Mutex was
created by instance 1, which is still coming up (it hasn't created its main
window yet), and instance 2 finds that the Mutex already exists, it tries to
find the window for Instance 1. But since Instance 1 is not yet there, this
code does not pop up the window for Instance 1. But that's OK. Because
Instance 1 has not yet created its window, it will proceed to create its
window successfully and pop up just like you'd expect. "
This is not always true, as your recent experience with the follies of
SetForegroundWindow() illustrate. The second instance has the focus, and if
the foreground lock timeout is not zero, then the first instance will be
prevented from bringing it's window to the foreground. To allow this, the
second instance can call:
AllowSetForegroundwindow(dwFirstInstanceProcessId);
And guess where you could store dwFirstInstanceProcessId? That's right, in
shared memory. :-)
-- David