Duplicating handles to Kernel side objects

This document describes when you should duplicate a handle in kernel side programming.

Duplicating a thread-relative handle in another thread

A handle in one thread (a thread-relative handle) may be duplicated in another thread within the same process.

Typically, thread B may want to access a Kernel object which already exists and for which thread A, within the same process, already holds a handle.

For example, if thread A has a handle on a semaphore, it is insufficient to pass a copy of the handle, an RSemaphore, to thread B. The handle passed to thread B does not refer to anything known by thread B. In order for thread B to gain a valid handle on the DLL, the handle must be duplicated.

Note that, in practice, real code may or may not want to duplicate a semaphore handle, however the principle remains valid.

In thread B, then:

...
RSemaphore cs;
cs.SetHandle(h.Handle()); 
                          // ...where  h  is an RSemaphore, the
                          // handle to the DLL, and
                          // passed from thread A code.
                                  
cs.Duplicate(tA);
                          // ...where  tA  is an RThread, the handle to
                          // thread A, and passed from threadA code.
                          // Duplicate also opens the resulting
                          // handle, cs.
...

The dotted line in the following diagram shows the effect of this:

Note that for process-relative handles, there is no need to use Duplicate(); the handle passed from thread A to thread B can be used directly.

Making specific handles from generic handles

There are two types of generic handle, one for threads and one for processes, both of which are created using the default constructor of the appropriate handle.

RThread  thisThread;  // Generic handle meaning "the current thread"
RProcess thisProcess; // Generic handle meaning "the current process"

An important fact about generic handles is that they make no claim on the object that they refer to, so you don't need to call Close() when you get rid of them. This is not true of specific handles, which always add a reference to the object that they refer to, preventing that object being fully destroyed until all specific handles have been closed.

Use Duplicate() to make a specific handle from a generic handle; for example:

RThread thisThread;                        // generic handle
TInt err=thisThread.Duplicate(thisThread);    // a specific handle
...
thisThread.Close();                        // don't forget.

Promoting a thread-relative handle to a process-wide handle

The second parameter passed to Duplicate() specifies whether the resulting handle is specific to the calling thread, or is valid for all threads in the same process.

Duplicate() offers a way of making a handle, which is specific to a thread, known to all the threads in a process.

This does not work for all handles but RLibrary is an example of one where it can make sense to promote an RLibrary thread-relative handle to a process-relative handle because this ensures that the library will not be automatically unloaded when the original thread terminates. For example:

...
_LIT(KMyLib,"MYLIB");
...
RLibrary threadLibrary;
err=threadLibrary.Load(KMyLib);        // Load up a DLL, this gives
                                       // a thread-specific handle.
RLibrary aDup=threadLibrary;           // Copies handle without
                                       // doing Open().
err=threadLibrary.Duplicate(RThread());// Overwrite the original.
if (err==KErrNone)
    {
       aDup.Close();                      // Close the original.
    }
...