C# Mutex always stuck on WaitOne - c#

I have one process that creates the mutex and immediately takes ownership, and then when a button is clicked, it releases it:
Mutex req_mutex = new Mutex(true, "req_mutex");
...
req_mutex.WaitOne(); // not required for first click
req_mutex.ReleaseMutex();
The other process is looping and checking if the mutex exists, when it does it waits for it to be released:
bool waitingForReqMutexCreation = true;
while (waitingForReqMutexCreation)
{
try
{
req_mutex = Mutex.OpenExisting("req_mutex", MutexRights.Synchronize);
waitingForReqMutexCreation = false;
}
catch (WaitHandleCannotBeOpenedException)
{
Thread.Sleep(1000);
}
}
...
req_mutex.WaitOne(); // wait for new request *********** problem here *********
req_mem.readFile(); // read request
req_mutex.ReleaseMutex(); // release req mutex for more requests
the problem is that the WaitOne doesn't continue even after the mutex was supposed to be released by the button in the first process.
Does anyone have an idea why that may be?

I think if you create the mutex with true (new Mutex(true, "req_mutex");)
you so should not need to call WaitOne() in that process.
The documentation says it is better to specify false for initiallyOwned when calling this constructor overload. https://msdn.microsoft.com/en-us/library/f55ddskf(v=vs.110).aspx
EDIT: ahh, you beat me to it :) ...

You are basically acquiring the mutex twice in your first application. You can see this by killing your first application while the second one is running, and you'll get an AbandonedMutexException (which means the Mutex gets acquired). Reproduced with the following, readline instead of button clicks:
namespace Mutex_1
{
class Program
{
static void Main(string[] args)
{
Mutex req_mutex = new Mutex(true, "req_mutex");
String t = string.Empty;
while (!t.Contains("q"))
{
Console.WriteLine("input: ");
t = Console.ReadLine();
Console.WriteLine("waiting for req_mutex");
req_mutex.WaitOne(); // not required for first click
Console.WriteLine("releasing req_mutex");
req_mutex.ReleaseMutex();
}
Console.ReadLine();
}
}
}
namespace Mutex_2
{
class Program
{
static void Main(string[] args)
{
Mutex req_mutex = null;
bool waitingForReqMutexCreation = true;
while (waitingForReqMutexCreation)
{
try
{
req_mutex = Mutex.OpenExisting("req_mutex");
waitingForReqMutexCreation = false;
}
catch (WaitHandleCannotBeOpenedException)
{
Console.WriteLine("req_mutex does not exist.");
Thread.Sleep(1000);
}
}
Console.WriteLine("req_mutex found");
req_mutex.WaitOne(); // wait for new request *********** problem here *********
Console.WriteLine("after req_mutex.WaitOne()");
req_mutex.ReleaseMutex(); // release req mutex for more requests
Console.ReadLine();
}
}
}
More evidence for this statement: calling ReleaseMutex twice in the parent will make things work on the first "click" (and crash the second time). You can fix this without throwing an exception by not acquiring the lock when it is created:
Mutex req_mutex = new Mutex(false, "req_mutex");

I think I found the answer to my own question...
Apparently the amount of WaitOne operations you do does matter.
I took ownership (true argument in the constructor) and did an additional WaitOne in the same thread assuming that it won't hurt.
Now in order to release the mutex I apparently had to call ReleaseMutex twice.
I guess I could still do it like this and call ReleaseMutex in a loop until an exception is thrown...

Related

Mutex under using block behaves differently

I was following this article regarding threading here. In that under section
Mutex the following code was there.
class OneAtATimePlease
{
static void Main()
{
// Naming a Mutex makes it available computer-wide. Use a name that's
// unique to your company and application (e.g., include your URL).
using (var mutex = new Mutex (false, "oreilly.com OneAtATimeDemo"))
{
// Wait a few seconds if contended, in case another instance
// of the program is still in the process of shutting down.
if (!mutex.WaitOne (TimeSpan.FromSeconds (3), false))
{
Console.WriteLine ("Another app instance is running. Bye!");
return;
}
RunProgram();
}
}
static void RunProgram()
{
Console.WriteLine ("Running. Press Enter to exit");
Console.ReadLine();
}
}
But when I run this the code is not behaving as expected, If I run the exe (the exe generated of the above) twice it should print "Another app instance is running. Bye!". But its not going to that block.
However if i remove the using block the code behaves correctly as expected.
Please help me. I am new to threading concepts.
UPDATE
Sorry for misleading. I actually didn't do like exactly written in that article.
My code as is,
internal class Program
{
/// <summary>
/// Entry point
/// </summary>
/// <param name="args">The arguments.</param>
internal static void Main(string[] args)
{
//Misc.RunAssemblies();
var threadingDemo = new ThreadingDemo();
threadingDemo.MutexDemo();
Console.ReadLine();
}
}
namespace LearnNet.Console
{
using System.Threading;
public class ThreadingDemo
{
public void MutexDemo()
{
using (var mutex = new Mutex(false, "Global\\oreilly.com OneAtATimeDemo"))
{
// Wait a few seconds if contended, in case another instance
// of the program is still in the process of shutting down.
if (!mutex.WaitOne(0, false))
{
System.Console.WriteLine("Another app instance is running. Bye!");
return;
}
RunProgram();
}
}
static void RunProgram()
{
System.Console.WriteLine("Running. Press Enter to exit");
}
}
}
This reproduces the issue which i explained above. And if i remove the using block it behaves correctly.
You have to understand how mutex works. WaitOne acquires it and ReleaseMutex or Disposing it releases it. At the end of using block (when control flow leaves it), mutex is Disposed (that's why using block exists in the first place), and so is released. In your updated code, mutex is acquired and then immediatly released after RunProgram statement, and any subsequent instances also acquire and release it immediatly.
When you don't use using block, you don't Dispose mutex and so don't release the mutex. When Console.ReadLine statement executes - process still holds mutex. When your process ends, mutex is still released, but it's not very good practice - better always release mutex explicitly.
As for why it works in the first code you posted (before update) - there Console.ReadLine() statement is inside using block, and so when control flow blocks on this statement - process still holds the mutex.

how to get PID of my app at runtime using C#

My app checks at startup if any other instance of the same is running already, if yes then it will close all other instances. For this I tried using Process.GetProcessByName("AppName") function and store all the process with AppName in processes[] array. Now i want to find the PID of current instance so that i can close all other instances of my app (which obviously have same name but different PIDs). But i am unable to find that even after lot of googling. Also how can i find the PID of an instance of my app which i have created with Process.Start("AppName.exe") function called from inside AppName.exe
OK, given problems with my other solution, see the following
In order to hook in between processes, you need some form of IPC. To use the simplicty of shared handles between EventWaitHandles, you could make each program listen for a cancellation flag.
public static EventWaitHAndle CancellationEvent =
new EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppCancel");
private object lockObject = new object();
And later...
Task.Run(() =>
{
while(true)
{
CancellationEvent.WaitOne();
lock(lockObject)
if(!thisIsCalling) // static bool to prevent this program from ending itself
Environment.Exit(0);
}
}
And then call the cancellation like so
lock(lockObject)
{
thisIsCalling = true;
CancellationEvent.Set();
thisIsCalling = false;
}
Why don't you just check equality with your current process?
var processes = Process.GetProcessByName("AppName");
foreach (var p in processes)
{
if (p != Process.GetCurrentProcess())
p.CloseMainWindow();
}
If you're interested in closing other instances of your app, why not do the opposite and prevent multiple instances from opening in the first place? Using EventWaitHandle can do this thusly:
bool created;
var eve = new System.Threading.EventWaitHandle(
false,
EventResetMode.AutoReset,
"MyAppHandle",
out created);
if(!created)
{
eve.Set();
Environment.Exit(-1); // Always use an exit error code if you're expecting to call from the console!
}
The handle parameter, "MyAppHandle" in this case, will be shared across the entire system, thus meaning not only will the out created paramete be false on secondary instaces, but you can use eve.Set() to cause the handle to fire acorss application. Set up a listening thread and this can allow a message loop to display a message when you attempt to open second instance.
Task.Run(() =>
{
while(true)
{
eve.WaitOne();
// Display an error here
}
}

why does Mutex.WaitOne() returns immediately in WPF?

I am trying to implement SigleInstance application per user session. I am using a local mutex for this. I have the following startup code.
public partial class App : Application
{
private const string applicationName = "EDisc.Client.Application";
private const string appGUID = "2AE55EA7-B392-42EF-BDFA-3DAFCE2B4B32";
public App()
{
bool isUnique = false;
using (var mutex = new Mutex(false, appGUID)) //Local mutex is local to the machine,it is per user,If u need a instance per machine,prefix appGUID with global.
{
try
{
try
{
isUnique = mutex.WaitOne(TimeSpan.FromSeconds(3), true); //wait in case first instance is shutting down.
if (isUnique) //If this is the first process.
{
this.Navigated += new NavigatedEventHandler(App_Navigated);
this.Exit += new ExitEventHandler(App_Exit);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
else //If process is already running.
{
LoggingHelper.LogMessage(CommonMessages.ANOTHER_APP_INSTANCE_OPEN, Source.EDiscClientApplication);
MessageBox.Show(CommonMessages.CLOSE_OTHER_APP_INSTANCE, CommonMessages.ANOTHER_APP_INSTANCE_OPEN,
MessageBoxButton.OK,
MessageBoxImage.Exclamation);
CloseApplicationInstance();
return;
}
}
catch (AbandonedMutexException)
{
}
}
finally
{
if (isUnique)
mutex.ReleaseMutex();
}
}
}
}
isUnique is always true irrespective of whether it is the first instance or second instance. mutex.waitone() returns immediately without waiting. I have been scratting my head for what can possibly be wrong in this code. Please help
Your code is releasing the mutex at the end of the App constructor - you keep it acquired only for a few microseconds (while registering those event handlers). You'll have to move the ReleaseMutex() call (and also the Dispose() call done by the using statement) to run at shutdown of your application.
I believe what is happening is that you are releasing the mutex in the finally block of the construtor. When the constructor exits, you are releasing the mutex and hence the next instance of the application can also aquire this mutex.
You can alternatively try:
public Mutex(
bool initiallyOwned,
string name,
out bool createdNew
)
So you check the out parameter which would return false if the mutex has already been created by another process

.NET: Using Mutex to make sure a webservice is only called once at a time

I'm using a Mutex to make sure a webservice is only running once at a time, but I can't get it 100% right with WaitOnce and ReleaseMutex.
I've got this:
private static Mutex mutex = new Mutex();
[WebMethod]
public bool TriggerAll()
{
bool ranJobs = false;
try
{
if (mutex.WaitOne(0, false))
{
Thread.Sleep(10000); // simulate a long operation
ranJobs = true;
}
}
finally
{
mutex.ReleaseMutex();
}
return ranJobs;
}
I'f I try to access the webservice twice immediately, the second call doesn't return false but I get a ApplicationException from mutex.ReleaseMutex ("objectsyncronization method was called from an onsyncronized codeblock" - roughly translated from swedish)
What's the best way to do this?
You're calling ReleaseMutex whether or not your WaitOne returned true. You should only call ReleaseMutex if you managed to acquire it:
if (mutex.WaitOne(0, false))
{
try
{
Thread.Sleep(10000); // simulate a long operation
ranJobs = true;
}
finally
{
mutex.ReleaseMutex();
}
}
Is your mutex being used by multiple processes or AppDomains by the way? If not, a normal CLR monitor (using Monitor.TryEnter) would be lighter.

Prevent multiple instances of a given app in .NET?

In .NET, what's the best way to prevent multiple instances of an app from running at the same time? And if there's no "best" technique, what are some of the caveats to consider with each solution?
Use Mutex. One of the examples above using GetProcessByName has many caveats. Here is a good article on the subject:
http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx
[STAThread]
static void Main()
{
using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
{
if(!mutex.WaitOne(0, false))
{
MessageBox.Show("Instance already running");
return;
}
Application.Run(new Form1());
}
}
private static string appGuid = "c0a76b5a-12ab-45c5-b9d9-d693faa6e7b9";
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
{
AppLog.Write("Application XXXX already running. Only one instance of this application is allowed", AppLog.LogMessageType.Warn);
return;
}
Here is the code you need to ensure that only one instance is running. This is the method of using a named mutex.
public class Program
{
static System.Threading.Mutex singleton = new Mutex(true, "My App Name");
static void Main(string[] args)
{
if (!singleton.WaitOne(TimeSpan.Zero, true))
{
//there is already another instance running!
Application.Exit();
}
}
}
Hanselman has a post on using the WinFormsApplicationBase class from the Microsoft.VisualBasic assembly to do this.
1 - Create a reference in program.cs ->
using System.Diagnostics;
2 - Put into void Main() as the first line of code ->
if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length >1)
return;
That's it.
After trying multiple solutions i the question. I ended up using the example for WPF here: http://www.c-sharpcorner.com/UploadFile/f9f215/how-to-restrict-the-application-to-just-one-instance/
public partial class App : Application
{
private static Mutex _mutex = null;
protected override void OnStartup(StartupEventArgs e)
{
const string appName = "MyAppName";
bool createdNew;
_mutex = new Mutex(true, appName, out createdNew);
if (!createdNew)
{
//app is already running! Exiting the application
Application.Current.Shutdown();
}
}
}
In App.xaml:
x:Class="*YourNameSpace*.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
It sounds like there are 3 fundamental techniques that have been suggested so far.
Derive from the Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase class and set the IsSingleInstance property to true. (I believe a caveat here is that this won't work with WPF applications, will it?)
Use a named mutex and check if it's already been created.
Get a list of running processes and compare the names of the processes. (This has the caveat of requiring your process name to be unique relative to any other processes running on a given user's machine.)
Any caveats I've missed?
i tried all the solutions here and nothing worked in my C# .net 4.0 project. Hoping to help someone here the solution that worked for me:
As main class variables:
private static string appGuid = "WRITE AN UNIQUE GUID HERE";
private static Mutex mutex;
When you need to check if app is already running:
bool mutexCreated;
mutex = new Mutex(true, "Global\\" + appGuid, out mutexCreated);
if (mutexCreated)
mutex.ReleaseMutex();
if (!mutexCreated)
{
//App is already running, close this!
Environment.Exit(0); //i used this because its a console app
}
I needed to close other istances only with some conditions, this worked well for my purpose
Using Visual Studio 2005 or 2008 when you create a project for an executable, on the properties windows inside the "Application" panel there is a check box named “Make single instance application” that you can activate to convert the application on a single instance application.
Here is a capture of the window I'm talking of:
This is a Visual Studio 2008 windows application project.
http://en.csharp-online.net/Application_Architecture_in_Windows_Forms_2.0—Single-Instance_Detection_and_Management
This is the code for VB.Net
Private Shared Sub Main()
Using mutex As New Mutex(False, appGuid)
If Not mutex.WaitOne(0, False) Then
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Application.Run(New Form1())
End Using
End Sub
This is the code for C#
private static void Main()
{
using (Mutex mutex = new Mutex(false, appGuid)) {
if (!mutex.WaitOne(0, false)) {
MessageBox.Show("Instance already running", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Application.Run(new Form1());
}
}
Use VB.NET!
No: really ;)
using Microsoft.VisualBasic.ApplicationServices;
The WindowsFormsApplicationBase from VB.Net provides you with a "SingleInstace" Property, which determines other Instances and let only one Instance run.
[STAThread]
static void Main() // args are OK here, of course
{
bool ok;
m = new System.Threading.Mutex(true, "YourNameHere", out ok);
if (! ok)
{
MessageBox.Show("Another instance is already running.");
return;
}
Application.Run(new Form1()); // or whatever was there
GC.KeepAlive(m); // important!
}
From: Ensuring a single instance of .NET Application
and: Single Instance Application Mutex
Same answer as #Smink and #Imjustpondering with a twist:
Jon Skeet's FAQ on C# to find out why GC.KeepAlive matters
This article simply explains how you can create a windows application with control on the number of its instances or run only single instance. This is very typical need of a business application. There are already lots of other possible solutions to control this.
https://web.archive.org/web/20090205153420/http://www.openwinforms.com/single_instance_application.html
http://www.codeproject.com/KB/cs/SingleInstancingWithIpc.aspx
You have to use System.Diagnostics.Process.
Check out: http://www.devx.com/tips/Tip/20044
(Note: this is a fun-solution! It works but uses bad GDI+ design to achieve this.)
Put an image in with your app and load it on startup. Hold it until the app exits. The user wont be able to start a 2nd instance. (Of course the mutex solution is much cleaner)
private static Bitmap randomName = new Bitmap("my_image.jpg");
Simply using a StreamWriter, how about this?
System.IO.File.StreamWriter OpenFlag = null; //globally
and
try
{
OpenFlag = new StreamWriter(Path.GetTempPath() + "OpenedIfRunning");
}
catch (System.IO.IOException) //file in use
{
Environment.Exit(0);
}
Normally it's done with a named Mutex (use new Mutex( "your app name", true ) and check the return value), but there's also some support classes in Microsoft.VisualBasic.dll that can do it for you.
This worked for me in pure C#. the try/catch is when possibly a process in the list exits during your loop.
using System.Diagnostics;
....
[STAThread]
static void Main()
{
...
int procCount = 0;
foreach (Process pp in Process.GetProcesses())
{
try
{
if (String.Compare(pp.MainModule.FileName, Application.ExecutablePath, true) == 0)
{
procCount++;
if(procCount > 1) {
Application.Exit();
return;
}
}
}
catch { }
}
Application.Run(new Form1());
}
Be sure to consider security when restricting an application to a single instance:
Full article:
https://blogs.msdn.microsoft.com/oldnewthing/20060620-13/?p=30813
We are using a named mutex with a fixed name in order to detect
whether another copy of the program is running. But that also means an
attacker can create the mutex first, thereby preventing our program
from running at all! How can I prevent this type of denial of service
attack?
...
If the attacker is running in the same security context as your
program is (or would be) running in, then there is nothing you can do.
Whatever "secret handshake" you come up with to determine whether
another copy of your program is running, the attacker can mimic it.
Since it is running in the correct security context, it can do
anything that the "real" program can do.
...
Clearly you can't protect yourself from an attacker running at the
same security privilege, but you can still protect yourself against
unprivileged attackers running at other security privileges.
Try setting a DACL on your mutex, here's the .NET way:
https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.mutexsecurity(v=vs.110).aspx
None of this answers worked for me because I needed this to work under Linux using monodevelop. This works great for me:
Call this method passing it a unique ID
public static void PreventMultipleInstance(string applicationId)
{
// Under Windows this is:
// C:\Users\SomeUser\AppData\Local\Temp\
// Linux this is:
// /tmp/
var temporaryDirectory = Path.GetTempPath();
// Application ID (Make sure this guid is different accross your different applications!
var applicationGuid = applicationId + ".process-lock";
// file that will serve as our lock
var fileFulePath = Path.Combine(temporaryDirectory, applicationGuid);
try
{
// Prevents other processes from reading from or writing to this file
var _InstanceLock = new FileStream(fileFulePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_InstanceLock.Lock(0, 0);
MonoApp.Logger.LogToDisk(LogType.Notification, "04ZH-EQP0", "Aquired Lock", fileFulePath);
// todo investigate why we need a reference to file stream. Without this GC releases the lock!
System.Timers.Timer t = new System.Timers.Timer()
{
Interval = 500000,
Enabled = true,
};
t.Elapsed += (a, b) =>
{
try
{
_InstanceLock.Lock(0, 0);
}
catch
{
MonoApp.Logger.Log(LogType.Error, "AOI7-QMCT", "Unable to lock file");
}
};
t.Start();
}
catch
{
// Terminate application because another instance with this ID is running
Environment.Exit(102534);
}
}

Categories

Resources