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 (1)

  1. ce_base says:

    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.

Skip to main content