I'm trying to mediate a small windows service, making it to wait for a signal from another process during startup. For sure I know that such approach may (or even will) sometimes lead to service startup timeout. That's not the case.
The problem is with named System.Thread.Sempaphore I use for mediation purposes. Semaphore is created and acquired somewhere else using following construct. There's no change GC has it as I explicitly break the execution right below given line for test purposes.
Boolean newOne;
System.Threading.Semaphore rootSemaphore =
new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out newOne);
Code above works well, obviously. Following code works well when being executed in debug mode or under console application:
Boolean createdNew;
System.Threading.Semaphore semaphore =
new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew);
if (createdNew)
throw new Exception("That's not what we wanted");
Exactly the same code fails when being executed as a part of Windows service:
static class Program
{
static void Main(string[] args)
{
Boolean createdNew;
System.Threading.Semaphore semaphore =
new System.Threading.Semaphore(1, 1, "DummyServiceSemaphore", out createdNew);
if (createdNew)
throw new Exception("That's not what we wanted");
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new Dummy() };
ServiceBase.Run(ServicesToRun);
}
}
I've been trying to use Mutex instead, however there was another issue with it - waiting application doesn't catch up when owner calls Mutex.ReleaseMutex();
UPDATE:
As per Anurag Ranjhan response I've edited semaphore creating routine as follows and the thingy now works fine:
Boolean newOne = false;
System.Security.Principal.SecurityIdentifier sid =
new System.Security.Principal.SecurityIdentifier(
System.Security.Principal.WellKnownSidType.WorldSid,
null);
System.Security.AccessControl.SemaphoreSecurity sec =
new System.Security.AccessControl.SemaphoreSecurity();
sec.AddAccessRule(new System.Security.AccessControl.SemaphoreAccessRule(
sid,
System.Security.AccessControl.SemaphoreRights.FullControl,
System.Security.AccessControl.AccessControlType.Allow));
System.Threading.Semaphore rootSemaphore =
new Semaphore(1, 1, "Global\\DummyServiceSemaphore", out newOne, sec);
Try using with Global\ prefix
System.Threading.Semaphore rootSemaphore =
new System.Threading.Semaphore(1, 1, @"Global\DummyServiceSemaphore", out newOne);
From the comment section of MSDN
If you're using a named Semaphore in Windows, the name you choose is governed by Kernel naming guidelines. Some of those guidelines also include the Kernel Object Namespaces1, which describes the context of the kernel object. By default, with Terminal Services installed, kernel objects like events are limited to the current Session. This is done so multiple sessions running in Terminal Services won't adversely affect one another. Kernel Object Namespaces describe using "Local", "Global" and "Session" prefixes to create kernel objects that can apply to specific namespaces and to communicate with or limit communication to processes of a specific scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With