Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DuplicateHandle(), use in first or second process?

Tags:

c++

winapi

ipc

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.

like image 371
Mike Trader Avatar asked May 04 '09 11:05

Mike Trader


4 Answers

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.

like image 193
Lucero Avatar answered Nov 03 '22 10:11

Lucero


Process Handle is different from process id. OpenProcess takes process id. Use something like...

HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());

like image 35
goto Avatar answered Nov 03 '22 10:11

goto


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).

like image 1
Cătălin Pitiș Avatar answered Nov 03 '22 10:11

Cătălin Pitiș


  1. Somehow, the second process needs to get its process ID to the first process. This can be obtained through GetCurrentProcessId()
  2. The first process now needs to use this ID to get a HANDLE to the second process: hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  3. Now you can duplicate the handle in the first process, using the REAL process handle of the second process and the pseudo-handle of the first process: DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hDupEvent, 0, FALSE, DUPLICATE_SAME_ACCESS);
  4. Remember to release the handle you created with OpenProcess eventually (I don't know what difference it would make, but you're supposed to...). Also, release BOTH handles to the event: the one given to the second process and the initial handle.
like image 1
Taylor Avatar answered Nov 03 '22 12:11

Taylor