Keeping a C# Mutex Alive in a Windows Service - c#

I've written a C# Windows Service application that reads a file via a timer delegate every 20 minutes or so, deserializes the content, and then clears the file. The file is written to by one or more client applications running on the same machine and I have chosen to use a Mutex to more or less "lock" the file while it is being deserialized and written to by the service.
I am doing this to avoid Exceptions in the rare occurrence that the client application and the service try to write to the file at the same time.
I create the Mutex inside of the Windows service via the following C# code (this is run every 20 minutes):
public void MyServiceFunction() {
Mutex sessMutex = new Mutex(false, "sessMutex");
sessMutex.WaitOne();
// Write to the file ......
sessMutex.ReleaseMutex();
}
In the client application I run the following:
public void MyClientFunction() {
Mutex mutex = Mutex.OpenExisting("sessMutex");
mutex.WaitOne();
// Write to the file ......
mutex.ReleaseMutex();
}
Now, if I start the Windows service and run the client application within a few minutes, everything works fine. However, after a few hours when attempting to execute the client application I get the following error:
No handle of the given name exists.
My question is, how do I prevent this error from occurring and "persisting" the Mutex.
Would storing the Mutex as property of the Windows service class work? Is using a Mutex the proper way to achieve the functionality I am looking for?
Thanks in advance for your help!

I don't understand why you treat the mutex differently in your client.
It should be the same code in both programs:
Mutex sessMutex = new Mutex(false, "sessMutex");
sessMutex.WaitOne();
// Write to the file ......
sessMutex.ReleaseMutex();
Create the mutex - if the mutex already exists in the system, this will return the existing mutex!
Try to lock
Write to file
Release lock

Apparently the service creates the mutex, locks it and start the file operations, then releases it, and then as soon as that method loses scope it's eligible for garbage collection. Subsequently, in the client, you seem to assume the mutex is still there.. yes storing it in the service scope may work, but then the client could still throw that exception if the service exited for whatever reason. your client will need to check if the mutex is still there. ps: then if it isn't, your service probably also isn't..

Related

By the c# code Windows service toggle and trying to remove a directory used by that service.

I'm trying to delete a directory used by a service. Because the directory is used by the service. That is why I have to stop the service. I can start or stop the service by the following code.
static void ToggleHostService(HostStatus serviceStatus)
{
var hostServiceName = "ServiceHost";
if (serviceStatus == HostStatus.run)
{
using (var controller = new ServiceController(hostServiceName))
{
if (controller.Status != ServiceControllerStatus.Running)
controller.Start();
controller.Refresh();
}
}
else if (serviceStatus == HostStatus.stop)
{
using (var controller = new ServiceController(hostServiceName))
{
if (controller.Status != ServiceControllerStatus.Stopped)
controller.Stop();
controller.Refresh();
}
}
}
But when I'm trying to delete the directory, I get exception as
Unhandled Exception: System.IO.IOException: The process cannot access
the file ' backup.wal' because it is being used by another process.
I can see in Service manager window that the service is really stopped. But why it still complains it can't access. To make sure I run the app/code in Admin mode. I tried Please tell me how can I really force delete that directory.
I assume that you have a separate application or service to delete the directory. If you are using the directory before for some reason, then there is possibility of locking the folder by that application or service. In order to free anything related to the directory by using the below code. This needs to be written just before the delete directory:
GC.Collect();
GC.WaitForPendingFinalizers();
Also check If(Directory.Exists()) before deleting the directory to handle relevant exceptions. You can use dispose() also to free up the memory used by the directory.
controller.Stop();
does not wait until the service is stopped, it just places the service in the "StopPending" state.
You have to wait until the service is stopped. I just looked into some code I wrote which does this and runs in production for some years and changed your code:
if (controller.Status != ServiceControllerStatus.Stopped)
{
controller.Stop();
// we do not need Refresh
// controller.Refresh();
controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
}
For me, this is the most obvious reason for your "file in use" problem.
But, also look at Lalithanand Barla's suggestion for checking if something still uses something in this dir.
There is an additional possible problem:
Normally, a Windows service starts one or more worker threads / tasks. In OnStop() method, a service should wait until all threads are stopped.
If the service you are trying to stop does not behave this way, there could be threads still alive which also cause file in use.
I don't really have a good solution for that, perhaps retrying your delete operation with some sleep (a second or so) between.
There could also be the possibilty that the service does not only has pending threads, but it also starts another process during OnStart. Then it will be even more difficult.

Get information about internal state of Windows Service

I have a Windows Service that I am writing in .NET C#. The service is going to act as a file processor. It just watches a directory for File Created events and adds these files to a queue for processing. A separate thread pulls files from the queue and processes them.
My question is whether there is a way to query the windows service to get its "state". I would like to be able to query the service some way and see a list of the files currently waiting in the queue etc.
I know this can be done in Linux via the /proc file system and I was wondering if there is anything similar for Windows. Any tips/pointers would be greatly appreciated.
If you are looking for a non-UI method (eg to write the names to a file or to standard output), it is possible to use the ExecuteCommand Method on the service.
ServiceController sc = new ServiceController("ServiceName");
sc.ExecuteCommand(255);
This simply passes this command to your your service and your service will handle it via the OnCustomCommand
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
if (command == 255
{
... // Your code here
}
}
You may need to store your queue/service status in a static variable so you can access it from the OnCustomCommand routine.
You could create a hosted WCF service inside of the windows service with whatever methods you need to access the state.
http://msdn.microsoft.com/en-us/library/ms733069.aspx
WCF would be good to do that, especially it can be hosted inside of Windows Service. Might be in your case it makes sense to use XML-RPC with WCF

Mutex not found even when OS reports that it exists

I am creating and using mutex in a windows service
using(var m = new Mutex(false,"mymutex")
{
m.WaitOne();
//to my things for a long time
m.ReleaseMutex();
}
On another program running with Administrator rights I do
Mutex.OpenExisting("mymutex")
and it throws mutex does not exist. I can see in the Resource manager that windows service has reference to the mutex.
What is wrong?
Operating system objects like Mutex have session scope. Your service runs in session 0 so its mutex is not visible to processes that run on the desktop session. The workaround is simple, prefix Global\ to the mutex name.
Ignorance is not bliss. EventWaitHandle.OpenExisting throws WaitHandleCannotBeOpenedException
It looks like the default behaviour changes from a Localsystem account to user account.

Negotiate two applications in separate domains

How can I notify another application which is in different domain that current running application has crashed?
in the other words, Is it possible to negotiate two different applications in separate domain?
Thanks in advance.
You can use named pipes for this sort of IPC. For this, look into System.IO.Pipes namespace and excellent NamedsPipeServerStream & NamedPipeClientStream classes.
Note that you can use anonymous pipes only for inter process communications within the same domain, while you can use named pipes for IPC in separate domains (i.e. across PCs on the same intranet).
Yes it is possible. How well this is supported in .NET types will vary depending on how you are going to make the determination of "has crashed".
Basically the monitoring application needs to supply credentials suitable to access the system that should be running the monitored application. This is exactly what one would do to copy a file to/from another domain by starting with something like:
net use \\Fileserver1.domain2.com\IPC$ /user:DOMAIN\USER PASSWORD
or its API equaivalent.
If you use WMI (this is the obvious approach, it is easy to list the processes on a remote system with a query for Win32_Process) you can supply credentials (eg. with the scripting interface or in .NET).
You can use the AppDomain.UnhandledException event to signal the other AppDomain, possibly through a named Mutex. Since they're system-wide, you could create one called "MyAppHasCrashed" and lock it immediately. When you hit an unhandled exception, you release the mutex. On the other side, have a thread that waits on the mutex. Since it's initially blocked, the thread will sit waiting. When an exception occurs, the thread resumes and you can handle the crash.
Mutex crashed = new Mutex(true, "AppDomain1_Crashed");
...
private void AppDomain_UnhandledException(...)
{
// do whatever you want to log / alert the user
// then unlock the mutex
crashed.ReleaseMutex();
}
Then, on the other side:
void CrashWaitThread()
{
try {
crashed = Mutex.OpenExisting("AppDomain1_Crashed");
}
catch (WaitHandleCannotBeOpenedException)
{
// couldn't open the mutex
}
crashed.WaitOne();
// code to handle the crash here.
}
It's a bit of a hack, but it works nicely for both inter-domain and inter-process cases.

How do I wait until a console application is idle?

I have a console application that starts up, hosts a bunch of services (long-running startup), and then waits for clients to call into it. I have integration tests that start this console application and make "client" calls. How do I wait for the console application to complete its startup before making the client calls?
I want to avoid doing Thread.Sleep(int) because that's dependent on the startup time (which may change) and I waste time if the startup is faster.
Process.WaitForInputIdle works only on applications with a UI (and I confirmed that it does throw an exception in this case).
I'm open to awkward solutions like, have the console application write a temp file when it's ready.
One option would be to create a named EventWaitHandle. This creates a synchronization object that you can use across processes. Then you have your 'client' applications wait until the event is signalled before proceeding. Once the main console application has completed the startup it can signal the event.
http://msdn.microsoft.com/en-us/library/41acw8ct(VS.80).aspx
As an example, your "Server" console application might have the following. This is not compiled so it is just a starting point :)
using System.Threading;
static EventWaitHandle _startedEvent;
static void main()
{
_startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, #"Global\ConServerStarted");
DoLongRunnningInitialization();
// Signal the event so that all the waiting clients can proceed
_startedEvent.Set();
}
The clients would then be doing something like this
using System.Threading;
static void main()
{
EventWaitHandle startedEvent = new EventWaitHandle(false, EventResetMode.ManualReset, #"Global\ConServerStarted");
// Wait for the event to be signaled, if it is already signalled then this will fall throught immediately.
startedEvent.WaitOne();
// ... continue communicating with the server console app now ...
}
What about setting a mutex, and removing it once start up is done. Have the client app wait until it can grab the mutex before it starts doing things.
Include an is ready check in the app's client interface, or have it return a not ready error if called before it's ready.
Create a WCF service that you can use for querying the status of the server process. Only start this service if a particular command is passed on the command line. The following traits will ensure a very fast startup of this service:
Host this service as the first operation of the client application
Use the net.tcp or net.pipe binding because they start very quickly
Keep this service as simple as possible to ensure that as long as the console application doesn't terminate, it will remain available
The test runner can attempt to connect to this service. Retry the attempt if it fails until the console application terminates or a reasonably short timeout period expires. As long as the console application doesn't terminate unexpectedly you can rely on this service to provide any additional information before starting your tests in a reasonably short period of time.
Since the two(the console application, and integration test app that makes client calls - as I understand) are separate application, so there should be a mechanism - a bridge - that would tell play as a mediator(socket, external file, registry, etc).
Another possibility could be that you come up with an average time the console takes to load the services and use that time in your test app; well, just thinking out loud!

Categories