How do clients know a service is ready?
Often clients start before servers, and need to be signaled
when the service
is ready. In this post we'll find a good solution to this problem.
Approach #1: Server
signals a named event, clients waits for the event.
Server:
//Create
manual reset event for service started
hEvent =
CreateEvent(NULL,TRUE,FALSE, SRV_STARTED_EVENT);
SetEvent(hEvent)
**
Clients:
// Create
manual reset event for service started
hServiceReadyEvent = CreateEvent(NULL,TRUE,FALSE, SRV_STARTED_EVENT);
WaitForSingleObject(hServiceReadyEvent)
Problems with #1:
What if the
clients accidentally create the named event as an auto reset event. E.g.
Broken Client:
// Accidently
create an auto reset event
hServiceReadyEvent = CreateEvent(NULL,FALSE,FALSE, SRV_STARTED_EVENT);
WaitForSingleObject(hServiceReadyEvent)
If the client code
runs after the server code runs everything works as expected. However, if the
client code runs before the server code, the event is created as an auto reset,
and the next client that goes to check the event will block forever. This bug can be
very hard to find if you have a broken client that only runs before the server a few
times.
Enough people have
had this problem, that the OS provides a solution. If
you create a
registry key under HKLM/System/Events, filesys will open the named event as
manual reset
unsignaled and keep them open for the lifetime of filesys.exe
Approach #2: Have
filesys create your named manual-reset at startup, then have client and server
use OpenEvent.
Registry Changes:
; @CESYSGEN IF
CE_MODULES_IGOR_SERVICE
; HIVE BOOT SECTION
[HKEY_LOCAL_MACHINE\SYSTEM\Events]
"IgorsServiceReadyEventName"="Event triggered after
IgorsService can be used"
; END HIVE BOOT
SECTION
; @CESYSGEN ENDIF
common code:
#define SRV_STARTED_EVENT
L"IgorsServiceReadyEventName"
Server:
//Open service ready event
hServiceReadyEvent =
OpenEvent(EVENT_ALL_ACCESS,FALSE,SRV_STARTED_EVENT);
SetEvent(hEvent)
Clients:
hServiceReadyEvent
= OpenEvent(EVENT_ALL_ACCESS,FALSE,SRV_STARTED_EVENT);
WaitForSingleObject(hServiceReadyEvent)
An interesting
side effect of this solution is if OpenEvent fails, the client will know the service is not in the image,
thus client code can be:
Clients that run on multiple CE configurations:
hServiceReadyEvent =
OpenEvent(EVENT_ALL_ACCESS,FALSE,SRV_STARTED_EVENT);
if
(hServiceReadyEvent == NULL)
{
// fatal
service is not present in this configuration.
}
WaitForSingleObject(hServiceReadyEvent)
[Author: Igor Dvorkin]
Comments
- Anonymous
October 11, 2005
Reference: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecoreos5/html/wce50conEventRegistration.asp
The other detail here is that many of the "ready" events have the "SYSTEM/" prefix on them, which prevents untrusted callers from creating or modifying the events, but also prevents untrusted callers from opening or waiting for them. So we created the IsNamedEventSignaled API to allow an untrusted caller to test whether an event is signaled. Alas, this gets rid of the benefit of being able to open and see if the event will NEVER get signaled -- or to block and wait for it.