Changeset 15898 in vbox for trunk/src/VBox
- Timestamp:
- Jan 12, 2009 2:42:51 PM (16 years ago)
- Location:
- trunk/src/VBox/HostServices/SharedClipboard
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h
r8155 r15898 25 25 #define LOG_GROUP LOG_GROUP_HGCM 26 26 #include <VBox/log.h> 27 28 enum {29 /** The number of milliseconds before the clipboard times out. */30 CLIPBOARDTIMEOUT = 200031 };32 27 33 28 struct _VBOXCLIPBOARDCONTEXT; -
trunk/src/VBox/HostServices/SharedClipboard/x11.cpp
r15883 r15898 194 194 195 195 LogFlowFunc(("u32Format=%02X\n", u32Format)); 196 /* Assert that no other transfer is in process (requests are serialised) 197 * and that the last transfer cleaned up properly. */ 198 AssertLogRelReturn( pCtx->pClient->data.pv == NULL 199 && pCtx->pClient->data.cb == 0 200 && pCtx->pClient->data.u32Format == 0, 201 VERR_WRONG_ORDER 202 ); 203 /* No one else (X11 or VBox) should currently be waiting. The first because 204 * requests from X11 are serialised and the second because VBox previously 205 * grabbed the clipboard, so it should not be waiting for data from us. */ 206 AssertLogRelReturn (ASMAtomicCmpXchgU32(&pCtx->waiter, 1, 0), VERR_DEADLOCK); 196 207 if (pClient == 0) 197 208 { 209 /* This can legitimately happen if we disconnect during a request for 210 * data from X11. */ 198 211 LogFunc(("host requested guest clipboard data after guest had disconnected.\n")); 199 212 pCtx->guestFormats = 0; … … 201 214 return VERR_TIMEOUT; 202 215 } 203 if (!( pCtx->pClient->data.pv == NULL204 && pCtx->pClient->data.cb == 0205 && pCtx->pClient->data.u32Format == 0))206 {207 LogRel(("vboxClipboardReadDataFromClient: a guest to host clipboard transfer has been requested, but another is in progress, or has not cleaned up properly.\n"));208 AssertMsgFailed(("A guest to host clipboard transfer has been requested, but another is in progress, or has not cleaned up properly.\n"));209 }210 211 /* Only one of the guest and the host should be waiting at any one time */212 if (!ASMAtomicCmpXchgU32(&pCtx->waiter, 1, 0))213 {214 LogRel(("vboxClipboardReadDataFromClient: deadlock situation - the host and the guest are both waiting for data from the other.\n"));215 return VERR_DEADLOCK;216 }217 216 /* Request data from the guest */ 218 217 vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format); 219 218 /* Which will signal us when it is ready. */ 220 if (RTSemEventWait(pCtx->waitForData, CLIPBOARDTIMEOUT) != VINF_SUCCESS) 221 { 222 LogRel(("vboxClipboardReadDataFromClient: vboxSvcClipboardReportMsg failed to complete within %d milliseconds\n", CLIPBOARDTIMEOUT)); 219 int rc = RTSemEventWait(pCtx->waitForData, RT_INDEFINITE_WAIT); 220 AssertLogRelRCSuccess(rc); 221 if (RT_FAILURE(rc)) 222 { 223 /* I believe this should not happen. Wait until the assertions arrive 224 * to prove the contrary. */ 223 225 pCtx->guestFormats = 0; 224 226 pCtx->waiter = 0; 225 return VERR_TIMEOUT;227 return rc; 226 228 } 227 229 pCtx->waiter = 0; … … 684 686 XtAppMainLoop(g_ctx.appContext); 685 687 g_ctx.formatList.clear(); 686 RTSemEventDestroy(g_ctx.waitForData);687 RTSemMutexDestroy(g_ctx.asyncMutex);688 688 LogRel(("Shared clipboard: host clipboard thread terminated successfully\n")); 689 689 return VINF_SUCCESS; … … 848 848 LogRel(("vboxClipboardDestroy: shutting down host clipboard\n")); 849 849 850 /* Drop the reference to the client, in case it is still there. This will 851 * cause any outstanding clipboard data requests from X11 to fail 852 * immediately. */ 853 g_ctx.pClient = NULL; 850 854 /* Set the termination flag. */ 851 855 XtAppSetExitFlag(g_ctx.appContext); … … 856 860 XSendEvent(XtDisplay(g_ctx.widget), XtWindow(g_ctx.widget), false, 0, &ev); 857 861 XFlush(XtDisplay(g_ctx.widget)); 862 if (g_ctx.eOwner == GUEST) 863 /* X11 may be waiting for data from VBox. At this point it is no 864 * longer going to arrive, and we must release it to allow the event 865 * loop to terminate. In this case the buffer where VBox would have 866 * written the clipboard data will still be empty and we will just 867 * return "no data" to X11. Any subsequent attempts to get the data 868 * from VBox will fail immediately as the client reference is gone. */ 869 RTSemEventSignal(g_ctx.waitForData); 858 870 do 859 871 { … … 863 875 } while ((VERR_TIMEOUT == rc) && (count < 300)); 864 876 if (RT_SUCCESS(rc)) 877 { 878 /* 879 * No one should be waiting on this by now. Justification: 880 * - Case 1: VBox is waiting for data from X11: 881 * Not possible, as it would be waiting on this thread. 882 * - Case 2: X11 is waiting for data from VBox: 883 * Not possible, as we checked that the X11 event thread exited 884 * successfully. 885 */ 886 RTSemEventDestroy(g_ctx.waitForData); 887 RTSemMutexDestroy(g_ctx.asyncMutex); 865 888 AssertRC(rcThread); 889 } 866 890 else 867 891 LogRel(("vboxClipboardDestroy: rc=%Rrc\n", rc)); … … 889 913 890 914 /* Only one client is supported for now */ 891 if (g_ctx.pClient != 0) 892 { 893 LogRel(("vboxClipboardConnect: attempted to connect, but a client appears to be already running.\n")); 894 AssertReturn(g_ctx.pClient == 0, VERR_NOT_SUPPORTED); 895 } 915 AssertLogRelReturn(g_ctx.pClient == 0, VERR_NOT_SUPPORTED); 896 916 897 917 pClient->pCtx = &g_ctx; … … 1045 1065 /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */ 1046 1066 LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc, 1047 1067 RT_SUCCESS(rc) ? ", g_ctx.pClient->data.cb == 0" : "")); 1048 1068 vboxClipboardEmptyGuestBuffer(); 1049 1069 return false; … … 1120 1140 /* If vboxClipboardReadDataFromVBox fails then pClient may be invalid */ 1121 1141 LogRelFunc (("vboxClipboardReadDataFromVBox returned %Rrc%s\n", rc, 1122 1142 RT_SUCCESS(rc) ? ", g_ctx.pClient->data.cb == 0" : "")); 1123 1143 vboxClipboardEmptyGuestBuffer(); 1124 1144 return false; … … 1319 1339 1320 1340 LogFlowFunc(("\n")); 1341 /* Drop requests that we receive too late. */ 1342 if (g_ctx.eOwner != GUEST) 1343 return false; 1321 1344 if ( (*atomSelection != g_ctx.atomClipboard) 1322 1345 && (*atomSelection != g_ctx.atomPrimary) … … 1475 1498 return VERR_NO_DATA; /* The guest thinks we have data and we don't */ 1476 1499 } 1477 /* Only one of the host and the guest should ever be waiting. */ 1478 if (!ASMAtomicCmpXchgU32(&g_ctx.waiter, 1, 0)) 1479 { 1480 LogRel(("vboxClipboardReadData: detected a deadlock situation - the host and the guest are waiting for each other.\n")); 1481 return VERR_DEADLOCK; 1482 } 1500 /* No one else (VBox or X11) should currently be waiting. The first because 1501 * requests from VBox are serialised and the second because X11 previously 1502 * grabbed the clipboard, so it should not be waiting for data from us. */ 1503 AssertLogRelReturn (ASMAtomicCmpXchgU32(&g_ctx.waiter, 1, 0), VERR_DEADLOCK); 1483 1504 g_ctx.requestHostFormat = g_ctx.hostTextFormat; 1484 1505 g_ctx.requestBuffer = pv; … … 1492 1513 vboxClipboardGetDataFromX11, reinterpret_cast<XtPointer>(g_ctx.pClient), 1493 1514 CurrentTime); 1494 /* When the data arrives, the vboxClipboardGet Proccallback will be called. The1515 /* When the data arrives, the vboxClipboardGetDataFromX11 callback will be called. The 1495 1516 callback will signal the event semaphore when it has processed the data for us. */ 1496 1517 1497 #ifdef RT_OS_SOLARIS 1498 /* 1499 * Trusted Xorg requires a bigger timeout. 1500 */ 1501 unsigned long cTimeoutMillies = CLIPBOARDTIMEOUT; 1502 if (is_system_labeled()) 1503 cTimeoutMillies = 1000 * 120; 1504 1505 if (RTSemEventWait(g_ctx.waitForData, cTimeoutMillies) != VINF_SUCCESS) 1506 #else 1507 if (RTSemEventWait(g_ctx.waitForData, CLIPBOARDTIMEOUT) != VINF_SUCCESS) 1508 #endif 1518 int rc = RTSemEventWait(g_ctx.waitForData, RT_INDEFINITE_WAIT); 1519 if (RT_FAILURE(rc)) 1509 1520 { 1510 /* No need to polute the release log for this. */1511 // LogRel(("vboxClipboardReadDataFromClient: XtGetSelectionValue failed to complete within %d milliseconds\n", CLIPBOARDTIMEOUT));1512 /* A time out can legitimately occur if a client is temporarily too busy to answer fast */1513 // g_ctx.hostTextFormat = INVALID;1514 // g_ctx.hostBitmapFormat = INVALID;1515 1521 g_ctx.waiter = 0; 1516 return VERR_TIMEOUT;1522 return rc; 1517 1523 } 1518 1524 g_ctx.waiter = 0; … … 1542 1548 LogFlowFunc (("called\n")); 1543 1549 1544 /* 1545 * The guest returns data that was requested in the WM_RENDERFORMAT handler. 1546 */ 1547 if (!( pClient->data.pv == NULL 1548 && pClient->data.cb == 0 1549 && pClient->data.u32Format == 0)) 1550 { 1551 LogRel(("vboxClipboardWriteData: clipboard data has arrived from the guest, but another transfer is in process or has not cleaned up properly.\n")); 1552 AssertMsgFailed(("vboxClipboardWriteData: clipboard data has arrived from the guest, but another transfer is in process or has not cleaned up properly.\n")); 1553 } 1550 /* Assert that no other transfer is in process (requests are serialised) 1551 * or has not cleaned up properly. */ 1552 AssertLogRelReturnVoid ( pClient->data.pv == NULL 1553 && pClient->data.cb == 0 1554 && pClient->data.u32Format == 0); 1554 1555 1555 1556 if (cb > 0) … … 1567 1568 RTSemEventSignal(g_ctx.waitForData); 1568 1569 } 1570
Note:
See TracChangeset
for help on using the changeset viewer.