Index: trunk/src/VBox/Additions/linux/module/vboxmod.c
===================================================================
--- trunk/src/VBox/Additions/linux/module/vboxmod.c	(revision 3141)
+++ trunk/src/VBox/Additions/linux/module/vboxmod.c	(revision 3142)
@@ -277,4 +277,100 @@
                address space. */
             return vbox_ioctl_hgcm_call(arg, vboxDev);
+        }
+
+        case IOCTL_VBOXGUEST_CLIPBOARD_CONNECT:
+        {
+            static uint32_t u32ClientID = 0;
+            VMMDevHGCMDisconnect *reqDisconnect = NULL;
+            VMMDevHGCMConnect *reqConnect = NULL;
+            size_t cbRequestSize;
+            int rc;
+
+            /* First, disconnect any old client. */
+            if (u32ClientID != 0)
+            {
+                /* get the request size */
+                cbRequestSize = vmmdevGetRequestSize(VMMDevReq_HGCMDisconnect);
+                /* request storage for the request */
+                rc = VbglGRAlloc((VMMDevRequestHeader **) &reqDisconnect, cbRequestSize,
+                                 VMMDevReq_HGCMDisconnect);
+                if (VBOX_FAILURE(rc))
+                {
+                    printk(KERN_ERR
+                          "vboxadd_ioctl: could not allocate request structure! rc = %d\n", rc);
+                    return -EFAULT;
+                }
+                /* now get the full request */
+                vmmdevInitRequest(&reqDisconnect->header.header, VMMDevReq_HGCMDisconnect);
+                reqDisconnect->u32ClientID = u32ClientID;
+
+                /* now issue the request */
+                rc = VbglGRPerform(&reqDisconnect->header.header);
+
+                /* asynchronous processing? */
+                if (rc == VINF_HGCM_ASYNC_EXECUTE)
+                {
+                    VMMDevHGCMRequestHeader *reqHGCM = &reqDisconnect->header;
+                    wait_event (vboxDev->eventq, reqHGCM->fu32Flags & VBOX_HGCM_REQ_DONE);
+                    rc = reqHGCM->header.rc;
+                }
+
+                /* failed? */
+                if (VBOX_FAILURE(rc) || VBOX_FAILURE(reqDisconnect->header.header.rc))
+                {
+                    printk(KERN_ERR "vboxadd_ioctl: request execution failed!\n");
+                    VbglGRFree(&reqDisconnect->header.header);
+                    return -EFAULT;
+                }
+            }
+
+            /* And connect... */
+            /* get the request size */
+            cbRequestSize = vmmdevGetRequestSize(VMMDevReq_HGCMConnect);
+            /* request storage for the request */
+            rc = VbglGRAlloc((VMMDevRequestHeader **) &reqConnect, cbRequestSize, VMMDevReq_HGCMConnect);
+            if (VBOX_FAILURE(rc))
+            {
+                printk(KERN_ERR
+                       "vboxadd_ioctl: could not allocate request structure! rc = %d\n", rc);
+                return -EFAULT;
+            }
+            /* now get the full request */
+            vmmdevInitRequest((VMMDevRequestHeader*)reqConnect, VMMDevReq_HGCMConnect);
+            reqConnect->loc.type = VMMDevHGCMLoc_LocalHost_Existing;
+            strcpy (reqConnect->loc.u.host.achName, "VBoxSharedClipboard");
+
+            /* now issue the request */
+            rc = VbglGRPerform(&reqConnect->header.header);
+
+            /* asynchronous processing? */
+            if (rc == VINF_HGCM_ASYNC_EXECUTE)
+            {
+                VMMDevHGCMRequestHeader *reqHGCM = &reqConnect->header;
+                wait_event (vboxDev->eventq, reqHGCM->fu32Flags & VBOX_HGCM_REQ_DONE);
+                rc = reqHGCM->header.rc;
+            }
+
+            /* failed? */
+            if (VBOX_FAILURE(rc) || VBOX_FAILURE(reqConnect->header.header.rc))
+            {
+                printk(KERN_ERR "vboxadd_ioctl: request execution failed!\n");
+                VbglGRFree(&reqConnect->header.header);
+                return -EFAULT;
+            }
+            else
+            {
+                /* success, copy the result data to user space */
+                u32ClientID = reqConnect->u32ClientID;
+                if (copy_to_user((void*)arg, (void*)&(reqConnect->u32ClientID), sizeof(uint32_t)))
+                {
+                    printk(KERN_ERR
+                           "vboxadd_ioctl: error copying request result to user space!\n");
+                    VbglGRFree(&reqConnect->header.header);
+                    return -EFAULT;
+                }
+            }
+            VbglGRFree(&reqConnect->header.header);
+            break;
         }
 
Index: trunk/src/VBox/Additions/linux/xclient/clipboard.cpp
===================================================================
--- trunk/src/VBox/Additions/linux/xclient/clipboard.cpp	(revision 3141)
+++ trunk/src/VBox/Additions/linux/xclient/clipboard.cpp	(revision 3142)
@@ -1365,11 +1365,23 @@
 void vboxClipboardDisconnect (void)
 {
+#if 0
     VMMDevHGCMDisconnect request;
+#endif
     LogFlowFunc(("\n"));
 
     AssertReturn(g_ctx.client != 0, (void) 0);
+#if 0
+    /* Currently, disconnecting is not needed, as the new "connect clipboard"
+       ioctl in the Guest Additions kernel module disconnects the last
+       connection made automatically.  The reason for this change was that
+       currently only one clipboard connection is allowed, and that if the
+       client holding that connection was terminated too abruptly, the
+       information needed to disconnect that connection was lost.  If the
+       subsystem is ever changed to allow several connections, this will have
+       to be rethought. */
     vmmdevInitRequest((VMMDevRequestHeader*)&request, VMMDevReq_HGCMDisconnect);
     request.u32ClientID = g_ctx.client;
     ioctl(g_ctx.sendDevice, IOCTL_VBOXGUEST_VMMREQUEST, (void*)&request);
+#endif
     LogFlowFunc(("returning\n"));
 }
@@ -1403,15 +1415,4 @@
 }
 
-void vboxClipboardSignalHandler(int number)
-{
-    LogFlowFunc(("number: %d\n", number));
-    vboxClipboardDisconnect();
-    if (g_ctx.daemonise == 0)
-    {
-        cout << "Received signal " << number << ".  Aborting" << endl;
-    }
-    LogFlowFunc(("exiting\n"));
-    exit(1);
-}
 
 /**
@@ -1422,58 +1423,28 @@
 int vboxClipboardConnect (void)
 {
-    VMMDevHGCMConnect request;
-    struct sigaction sSigAction;
-
     LogFlowFunc(("\n"));
-    memset(&request, 0, sizeof(request));
-    request.u32ClientID = 0;
+    int rc;
     /* Only one client is supported for now */
     AssertReturn(g_ctx.client == 0, VERR_NOT_SUPPORTED);
 
-    vmmdevInitRequest((VMMDevRequestHeader*)&request, VMMDevReq_HGCMConnect);
-    request.loc.type = VMMDevHGCMLoc_LocalHost_Existing;
-    strcpy (request.loc.u.host.achName, "VBoxSharedClipboard");
-    if (ioctl(g_ctx.sendDevice, IOCTL_VBOXGUEST_VMMREQUEST, (void*)&request) >= 0)
-    {
-        if (VBOX_SUCCESS(request.header.header.rc))
-        {
-            if (request.u32ClientID == 0)
-            {
-                cout << "We got an invalid client ID of 0!" << endl;
-                return VERR_NOT_SUPPORTED;
-            }
-            g_ctx.client = request.u32ClientID;
-            g_ctx.eOwner = HOST;
-        }
-        else
-        {
-            Log(("Error connecting to host.  header.rc = %Vrc\n", request.header.header.rc));
-            cout << "Unable to connect to the host system." << endl;
-            LogFlowFunc(("returned VERR_NOT_SUPPORTED\n"));
+    rc = ioctl(g_ctx.sendDevice, IOCTL_VBOXGUEST_CLIPBOARD_CONNECT, (void*)&g_ctx.client);
+    if (rc >= 0)
+    {
+        if (g_ctx.client == 0)
+        {
+            cout << "We got an invalid client ID of 0!" << endl;
             return VERR_NOT_SUPPORTED;
         }
-
+        g_ctx.eOwner = HOST;
     }
     else
     {
-        Log(("Error performing VMM request ioctl. errno = %d\n", errno));
-        cout << "The VirtualBox device in the guest is not responding correctly." << endl;
+        Log(("Error connecting to host.  rc = %d (%s)\n", rc, strerror(-rc)));
+        cout << "Unable to connect to the host system." << endl;
         LogFlowFunc(("returned VERR_NOT_SUPPORTED\n"));
         return VERR_NOT_SUPPORTED;
     }
-    /* If the programme exits without disconnecting from the shared clipboard service, we
-       will need to reboot the guest in order to use it again.  So we set handlers for as
-       many fatal conditions as possible which disconnect and exit the programme. */
+    /* Set an X11 error handler, so that we don't die when we get BadAtom errors. */
     XSetErrorHandler(vboxClipboardXLibErrorHandler);
-    sSigAction.sa_handler = vboxClipboardSignalHandler;
-    sigemptyset(&sSigAction.sa_mask);
-    sSigAction.sa_flags = 0;
-    sigaction(SIGSEGV, &sSigAction, 0);
-    sigaction(SIGBUS, &sSigAction, 0);
-    sigaction(SIGUSR1, &sSigAction, 0);
-    sigaction(SIGINT, &sSigAction, 0);
-    sigaction(SIGQUIT, &sSigAction, 0);
-    sigaction(SIGTERM, &sSigAction, 0);
-    sigaction(SIGTRAP, &sSigAction, 0);
     LogFlowFunc(("returned VINF_SUCCESS\n"));
     return VINF_SUCCESS;
