tags:

views:

782

answers:

2

The Windows API DuplicateHandle() http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx Requires the Object handle to be duplicated and a handle to both the original process AND the other process that you want to use the duplicated handle in.

I am assuming that if I have two UNRELATED processes, I could call DuplicateHandle() in either one so long as I had the required handles available?

My Question is about using a Pipe to communicate between the two processes to achieve this with an Event.

In the first process I CreateEvent(). Now I want to use WaitForSingleObject() in the second process.

If I try to duplicate the handle in the first process, I will need to first send the second process handle to the first process via the pipe, duplicate the handle and then send the handle over to the second process?

Alternativly, I could begin by sending the first process handle and the Event handle to the second process and just duplicate it there.

Is there a reason I should choose one over the other?

To add a wrinkle, the Event handle is actually inherited from the parent process that actually called the first process (which is a CGI application). If that Event handle was created with HANDLE_DO_NOT_DUPLICATE (something like that) then can I in fact use DuplicateHandle() to duplicate it for the second process?

Response:

Well I could create a new NAMED event in the first process and find it in the second process as suggested, but I am trying to DUPLICATE the event that was created in the parent of the first process and foreward it to the second process. This event is not a named event so I need to use DuplicateHandle().

I am using a pipe for the IPC. I am realizing that DuplicateHandle() will have to be called in the first process because the event handle is out of context when sent to the second process.

        hProcPseudo  = GetCurrentProcess() 

    //Then call either:
        lpRealHandle = OpenProcess( PROCESS_DUP_HANDLE, 0, hProcPseudo ) 
//This fails with GetLastError= 87 - The parameter is incorrect ???
// same thing with PROCESS_ALL_ACCESS ??


    //OR
        lRet = DuplicateHandle( hProcPseudo, hProcPseudo, hProcPseudo, lpRealHandle, DUPLICATE_SAME_ACCESS, 0, 0 )

    //then I can Duplicate my Event Handle in the first thread with:
        lRet = DuplicateHandle( hLocalProcess, hEvent, lpRealHandle, hDupEvent, DUPLICATE_SAME_ACCESS, 0, 0)

The second process converts its handle with DuplicateHandle() detailed above converting

hProcPseudo= 4294967295

to

hProcess= 152

Then I pass this process handle to the first process via the named pipe. In the first process (where the event handle is valid) I call Duplicate handle:

DuplicateHandle( hFirstProcess, hEvent, hSecondProc, hDupEvent, DUPLICATE_SAME_ACCESS, 0, 0)

Unfortunatly I get the error:

DuplicateHandle hPipeFCGI GetLastError= 6 - The handle is invalid.

Further testing (substituting hFirstProcess) reveals it is hSecondProc that is invalid!??

Big Mystery.

+1  A: 

If I understood correctly, you want to synchronize two unrelated processes through the same event. If so, you can use named events.

Create one using CreateEvent API function, provide it a name, then from the second process use OpenEvent API function, specifying the name of the event.

You have similar functions for other synchronization objects, such as mutexes (OpenMutex) or semaphores (OpenSemaphore).

Cătălin Pitiș
See above.I am seeing an identical value for GetCurrentProcess() - used in DuplicateHandle() - in BOTH processes. That doesnt seem right? Why is this?
Mike Trader
What kind of handle did you tried to duplicate with DuplicateHandle? AFAIK, the process that created the handle (using CreateXXXX functions) is the owner of that created object.
Cătălin Pitiș
+1  A: 

Use a named pipe or mailslots for IPC, this should work reliably for your purpose. If you need to wait, use named wait handles.

Otherwise, I'd choose to do DuplicateHandle in the second process in order to set the handle ownership correctly.

Lucero
I am using a NamedPipe successfully for the IPC yes. I can't duplicate the handle in the second process because the handle from the first process has no context in the second process. I also puzzled by the fact that GetCurrentProcess() returns the same value in both processes...
Mike Trader
That's because GetCurrentProcess() returns a constant pseudo-handle to the process first, which you need to resolve before you pass it to the other process via RPC. See the documentation here: http://msdn.microsoft.com/en-us/library/ms683179(VS.85).aspx
Lucero
Ahhh ok, so deso the code above look ok?It seems odd to call DuplicateHandle() with the pseudo handle as the first three arguments!
Mike Trader
The resolved handle is still not valid in the other process (see details above)
Mike Trader
Yes, that's because the handle still belongs to the other process. So on the target process, you need to duplicate the process handle once more: DuplicateHandle( hFirstProcessFromPipe, hFirstProcessFromPipe, GetCurrentProcess(), hFirstProcess, DUPLICATE_SAME_ACCESS, 0, 0)
Lucero
That's what I meant with the "ownership"; each process has its own set of handles, therefore, after you've acquired a valid handle to the process itself, this handle is not valid in another process unless you do DuplicateHandle again to transfer the handle into your second process space.
Lucero
OK That makes sense. xfer the real second process handle via a pipe over to the first process, then create a local version of that handle.The problem is DuplicateHandle() doesnt like the handle hFirstProcessFromPipe... its not valid in the first process for the reasons you gave, so I cant use it to duplicate with. I need some kind of global process handle to send through the pipe perhaps?
Mike Trader
Pass a PID over the pipe instead of a handle. The PID can be converted to a procedd handle with OpenProcess, and getting the PID is easy (XP SP1 and after): http://msdn.microsoft.com/en-us/library/ms683215(VS.85).aspx
Lucero