Index: /trunk/src/VBox/HostDrivers/Support/Makefile
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile	(revision 387)
@@ -56,4 +56,5 @@
 	include/iprt/mem.h=$(PATH_ROOT)/include/iprt/mem.h \
 	include/iprt/param.h=$(PATH_ROOT)/include/iprt/param.h \
+	include/iprt/process.h=$(PATH_ROOT)/include/iprt/process.h \
 	include/iprt/semaphore.h=$(PATH_ROOT)/include/iprt/semaphore.h \
 	include/iprt/spinlock.h=$(PATH_ROOT)/include/iprt/spinlock.h \
Index: /trunk/src/VBox/HostDrivers/Support/SUPDRV.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDRV.h	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDRV.h	(revision 387)
@@ -543,11 +543,9 @@
     /** The process (id) of the session. (Set by the OS part.) */
     RTPROCESS                   Process;
+    /** Which process this session is associated with. */
+    RTR0PROCESS                 R0Process;
 #if defined(__DARWIN__) || defined(__OS2__)
     /** Pointer to the next session with the same has. */
     PSUPDRVSESSION              pNextHash;
-#endif
-#if defined(__DARWIN__)
-    /** Pointer to the org_virtualbox_SupDrvClient client that's associated with the session. */
-    void                       *pvClient;
 #endif
 } SUPDRVSESSION;
@@ -669,4 +667,5 @@
 int  VBOXCALL   supdrvCreateSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION *ppSession);
 void VBOXCALL   supdrvCloseSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
+void VBOXCALL   supdrvCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
 int  VBOXCALL   supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, uint64_t u64NanoTS, unsigned uUpdateHz);
 void VBOXCALL   supdrvGipTerm(PSUPGLOBALINFOPAGE pGip);
Index: /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c	(revision 387)
@@ -327,6 +327,34 @@
 void VBOXCALL supdrvCloseSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
 {
+    /*
+     * Cleanup the session first.
+     */
+    supdrvCleanupSession(pDevExt, pSession);
+
+    /*
+     * Free the rest of the session stuff.
+     */
+    RTSpinlockDestroy(pSession->Spinlock);
+    pSession->Spinlock = NIL_RTSPINLOCK;
+    pSession->pDevExt = NULL;
+    RTMemFree(pSession);
+    dprintf2(("supdrvCloseSession: returns\n"));
+}
+
+
+/**
+ * Shared code for cleaning up a session (but not quite freeing it).
+ *
+ * This is primarily intended for MAC OS X where we have to clean up the memory
+ * stuff before the file handle is closed.
+ *
+ * @param   pDevExt     Device extension.
+ * @param   pSession    Session data.
+ *                      This data will be freed by this routine.
+ */
+void VBOXCALL supdrvCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
+{
     PSUPDRVBUNDLE       pBundle;
-    dprintf(("supdrvCloseSession: pSession=%p\n", pSession));
+    dprintf(("supdrvCleanupSession: pSession=%p\n", pSession));
 
     /*
@@ -429,4 +457,5 @@
                 AssertRC(rc); /** @todo figure out how to handle this. */
                 pBundle->aMem[i].MemObj = NIL_RTR0MEMOBJ;
+                pBundle->aMem[i].eType = MEMREF_TYPE_UNUSED;
             }
 
@@ -454,4 +483,5 @@
                         break;
                 }
+                pBundle->aMem[i].eType = MEMREF_TYPE_UNUSED;
             }
 #endif /* !USE_NEW_OS_INTERFACE */
@@ -472,5 +502,5 @@
 
     /*
-     * Loaded images needs to be dereferenced and possibly freed.
+     * Loaded images needs to be dereferenced and possibly freed up.
      */
     RTSemFastMutexRequest(pDevExt->mtxLdr);
@@ -513,13 +543,4 @@
     }
     dprintf2(("umapping GIP - done\n"));
-
-    /*
-     * Free the rest of the session stuff.
-     */
-    RTSpinlockDestroy(pSession->Spinlock);
-    pSession->Spinlock = NIL_RTSPINLOCK;
-    pSession->pDevExt = NULL;
-    RTMemFree(pSession);
-    dprintf2(("supdrvCloseSession: returns\n"));
 }
 
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 387)
@@ -37,4 +37,5 @@
 #include <iprt/spinlock.h>
 #include <iprt/semaphore.h>
+#include <iprt/process.h>
 #include <iprt/alloc.h>
 
@@ -114,9 +115,9 @@
     virtual bool initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type);
     virtual bool start(IOService *pProvider);
-    virtual void stop(IOService *pProvider);
     virtual IOReturn clientClose(void);
     virtual IOReturn clientDied(void);
     virtual bool terminate(IOOptionBits fOptions = 0);
     virtual bool finalize(IOOptionBits fOptions);
+    virtual void stop(IOService *pProvider);
 };
 
@@ -313,5 +314,6 @@
             pSession->Gid = pCred->cr_gid;
         }
-        pSession->Process = proc_pid(pProcess);
+        pSession->Process = RTProcSelf();
+        pSession->R0Process = RTR0ProcHandleSelf();
 
         /*
@@ -768,8 +770,56 @@
 IOReturn org_virtualbox_SupDrvClient::clientDied(void)
 {
-    dprintf(("org_virtualbox_SupDrvClient::clientDied([%p])\n", this));
-
-    /* IOUserClient::clientDied() only calls calls close... */
+    dprintf(("org_virtualbox_SupDrvClient::clientDied([%p]) m_Task=%p R0Process=%p Process=%d\n",
+             this, m_Task, RTR0ProcHandleSelf(), RTProcSelf()));
+
+    /*
+     * Do early session cleanup (if there is a session) so
+     * we avoid hanging in vm_map_remove().
+     */
+    const RTR0PROCESS   R0Process = (RTR0PROCESS)m_Task;
+    RTSPINLOCKTMP       Tmp = RTSPINLOCKTMP_INITIALIZER;
+    RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
+    for (unsigned i = 0; i < RT_ELEMENTS(g_apSessionHashTab); i++)
+    {
+        for (PSUPDRVSESSION pSession = g_apSessionHashTab[i]; pSession; pSession = pSession->pNextHash)
+        {
+            dprintf2(("pSession=%p R0Process=%p (=? %p)\n", pSession, pSession->R0Process, R0Process));
+            if (pSession->R0Process == R0Process)
+            {
+                /*
+                 * It is safe to leave the spinlock here; the session shouldn't be able
+                 * to go away while we're cleaning it up, changes to pNextHash will not
+                 * harm us, and new sessions can't possibly be added for this process.
+                 */
+                RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
+                supdrvCleanupSession(&g_DevExt, pSession);
+                RTSpinlockAcquireNoInts(g_Spinlock, &Tmp);
+            }
+        }
+    }
+    RTSpinlockReleaseNoInts(g_Spinlock, &Tmp);
+
+    /* IOUserClient::clientDied() calls close... */
     return IOUserClient::clientDied();
+}
+
+
+/**
+ * Terminate the service (initiate the destruction).
+ */
+bool org_virtualbox_SupDrvClient::terminate(IOOptionBits fOptions)
+{
+    dprintf(("org_virtualbox_SupDrvClient::terminate([%p], %#x)\n", this, fOptions));
+    return IOUserClient::terminate(fOptions);
+}
+
+
+/**
+ * The final stage of the client service destruction.
+ */
+bool org_virtualbox_SupDrvClient::finalize(IOOptionBits fOptions)
+{
+    dprintf(("org_virtualbox_SupDrvClient::finalize([%p], %#x)\n", this, fOptions));
+    return IOUserClient::finalize(fOptions);
 }
 
@@ -784,22 +834,2 @@
 }
 
-
-/**
- * Terminate the service (initiate the destruction).
- */
-bool org_virtualbox_SupDrvClient::terminate(IOOptionBits fOptions)
-{
-    dprintf(("org_virtualbox_SupDrvClient::terminate([%p], %#x)\n", this, fOptions));
-    return IOUserClient::terminate(fOptions);
-}
-
-
-/**
- * The final stage of the client service destruction.
- */
-bool org_virtualbox_SupDrvClient::finalize(IOOptionBits fOptions)
-{
-    dprintf(("org_virtualbox_SupDrvClient::finalize([%p], %#x)\n", this, fOptions));
-    return IOUserClient::finalize(fOptions);
-}
-
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp	(revision 387)
@@ -25,8 +25,10 @@
 *   Header Files                                                               *
 *******************************************************************************/
+#define LOG_GROUP LOG_GROUP_SUP
 #include <VBox/types.h>
 #include <VBox/sup.h>
 #include <VBox/param.h>
 #include <VBox/err.h>
+#include <VBox/log.h>
 #include <iprt/path.h>
 #include <iprt/assert.h>
@@ -41,4 +43,6 @@
 #include <unistd.h>
 #include <stdlib.h>
+#include <mach/mach_port.h>
+#include <IOKit/IOKitLib.h>
 
 
@@ -48,4 +52,6 @@
 /** BSD Device name. */
 #define DEVICE_NAME     "/dev/vboxdrv"
+/** The IOClass key of the service (see SUPDrv-darwin.cpp / Info.plist). */
+#define IOCLASS_NAME    "org_virtualbox_SupDrv"
 
 
@@ -54,5 +60,9 @@
 *******************************************************************************/
 /** Handle to the open device. */
-static int      g_hDevice = -1;
+static int              g_hDevice = -1;
+/** The IOMasterPort. */
+static mach_port_t      g_MasterPort = 0;
+/** The current service connection. */
+static io_connect_t     g_Connection = NULL;
 
 
@@ -66,16 +76,63 @@
 
     /*
-     * Try open the device.
+     * Open the IOKit client first - The first step is finding the service.
+     */
+    mach_port_t MasterPort;
+    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort);
+    if (kr != kIOReturnSuccess)
+    {
+        LogRel(("IOMasterPort -> %d\n", kr));
+        return VERR_GENERAL_FAILURE;
+    }
+
+    CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_NAME);
+    if (!ClassToMatch)
+    {
+        LogRel(("IOServiceMatching(\"%s\") failed.\n", IOCLASS_NAME));
+        return VERR_GENERAL_FAILURE;
+    }
+
+    /* Create an io_iterator_t for all instances of our drivers class that exist in the IORegistry. */
+    io_iterator_t Iterator;
+    kr = IOServiceGetMatchingServices(g_MasterPort, ClassToMatch, &Iterator);
+    if (kr != kIOReturnSuccess)
+    {
+        LogRel(("IOServiceGetMatchingServices returned %d\n", kr));
+        return VERR_GENERAL_FAILURE;
+    }
+
+    /* Get the first item in the iterator and release it. */
+    io_service_t ServiceObject = IOIteratorNext(Iterator);
+    IOObjectRelease(Iterator);
+    if (!ServiceObject)
+    {
+        LogRel(("Couldn't find any matches.\n"));
+        return VERR_GENERAL_FAILURE;
+    }
+
+    /*
+     * Open the service.
+     * This will cause the user client class in SUPDrv-darwin.cpp to be instantiated.
+     */
+    kr = IOServiceOpen(ServiceObject, mach_task_self(), 0, &g_Connection);
+    IOObjectRelease(ServiceObject);
+    if (kr != kIOReturnSuccess)
+    {
+        LogRel(("IOServiceOpen returned %d\n", kr));
+        return VERR_GENERAL_FAILURE;
+    }
+
+    /*
+     * Now, try open the BSD device.
      */
     g_hDevice = open(DEVICE_NAME, O_RDWR, 0);
     if (g_hDevice < 0)
     {
-        /*
-         * Try load the device.
-         */
-        //todo suplibOsLoadKernelModule();
-        g_hDevice = open(DEVICE_NAME, O_RDWR, 0);
-        if (g_hDevice < 0)
-            return RTErrConvertFromErrno(errno);
+        int rc = errno;
+        LogRel(("Failed to open \"%s\", errno=%d\n", rc));
+        kr = IOServiceClose(g_Connection);
+        if (kr != kIOReturnSuccess)
+            LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
+        return RTErrConvertFromErrno(rc);
     }
 
@@ -98,4 +155,18 @@
             AssertFailed();
         g_hDevice = -1;
+    }
+
+    /*
+     * Close the connection to the IOService and destroy the connection handle.
+     */
+    if (g_Connection)
+    {
+        kern_return_t kr = IOServiceClose(g_Connection);
+        if (kr != kIOReturnSuccess)
+        {
+            LogRel(("Warning: IOServiceClose(%p) returned %d\n", g_Connection, kr));
+            AssertFailed();
+        }
+        g_Connection = NULL;
     }
 
Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 387)
@@ -27,4 +27,5 @@
 #include <iprt/semaphore.h>
 #include <iprt/initterm.h>
+#include <iprt/process.h>
 #include <iprt/err.h>
 #include <iprt/mem.h>
@@ -221,5 +222,5 @@
 
 #ifdef __AMD64__
-/** 
+/**
  * Memory for the executable memory heap (in IPRT).
  */
@@ -233,5 +234,5 @@
         ".size g_abExecMemory, 1572864\n\t"
         ".text\n\t");
-#endif 
+#endif
 
 
@@ -363,7 +364,7 @@
 nmi_activated:
 #  endif
-                printk(KERN_ERR DEVICE_NAME 
+                printk(KERN_ERR DEVICE_NAME
                 ": NMI watchdog active -- refused to load the kernel module! Please disable\n"
-                                DEVICE_NAME 
+                                DEVICE_NAME
                 ": the NMI watchdog by specifying 'nmi_watchdog=0' at kernel command line.\n");
                 return -EINVAL;
@@ -534,5 +535,6 @@
         pSession->Uid       = current->euid;
         pSession->Gid       = current->egid;
-        pSession->Process   = (RTPROCESS)current->tgid;
+        pSession->Process   = RTProcSelf();
+        pSession->R0Process = RTR0ProcHandleSelf();
     }
 
Index: /trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp	(revision 386)
+++ /trunk/src/VBox/HostDrivers/Support/win32/SUPDrv-win32.cpp	(revision 387)
@@ -223,5 +223,6 @@
         pSession->Uid       = NIL_RTUID;
         pSession->Gid       = NIL_RTGID;
-        pSession->Process   = NIL_RTPROCESS;
+        pSession->Process   = RTProcSelf();
+        pSession->R0Process = RTR0ProcHandleSelf();
         pFileObj->FsContext = pSession;
     }
