Răsfoiți Sursa

display: mitigate deadlock on scanout texture

A race on the server side could allow the same pipe to be sent multiple
times causing the read() to block. This mitigates that situations but does
not completely fix the fact that an older scanout texture is actually the
most recent. However, by the time we discover this, we might have already
thrown that out for a stale texture that was sent after. This hopefully will
not be an issue because the IOSurfaceLookup would fail both times but if the
resolution happened to change in between, we could get bad data until the
next scanout. All of this would be properly mitigated when we implement a
better IPC solution than the current hack which is sending the global
IOSurface ID through a pipe.

Fixes #5
osy 8 luni în urmă
părinte
comite
4aa7eea1de
1 a modificat fișierele cu 9 adăugiri și 8 ștergeri
  1. 9 8
      Sources/CocoaSpice/CSDisplay.m

+ 9 - 8
Sources/CocoaSpice/CSDisplay.m

@@ -444,11 +444,7 @@ static void cs_gl_draw(SpiceDisplayChannel *channel,
 - (void)rebuildScanoutTextureWithScanout:(SpiceGlScanout)scanout {
 - (void)rebuildScanoutTextureWithScanout:(SpiceGlScanout)scanout {
     IOSurfaceID iosurfaceid = 0;
     IOSurfaceID iosurfaceid = 0;
     IOSurfaceRef iosurface = NULL;
     IOSurfaceRef iosurface = NULL;
-    if (read(scanout.fd, &iosurfaceid, sizeof(iosurfaceid)) != sizeof(iosurfaceid)) {
-        SPICE_DEBUG("[CocoaSpice] Failed to read scanout fd: %d", scanout.fd);
-        perror("read");
-        return;
-    }
+
     // check for POLLHUP which indicates the surface ID is stale as the sender has deallocated the surface
     // check for POLLHUP which indicates the surface ID is stale as the sender has deallocated the surface
     struct pollfd ufd = {0};
     struct pollfd ufd = {0};
     ufd.fd = scanout.fd;
     ufd.fd = scanout.fd;
@@ -458,11 +454,16 @@ static void cs_gl_draw(SpiceDisplayChannel *channel,
         perror("poll");
         perror("poll");
         return;
         return;
     }
     }
-    if ((ufd.revents & POLLHUP) != 0) {
-        SPICE_DEBUG("[CocoaSpice] Stale surface id %x read from fd %d, ignoring", iosurfaceid, scanout.fd);
+    if ((ufd.revents & (POLLHUP | POLLIN)) != POLLIN) {
+        SPICE_DEBUG("[CocoaSpice] Ignoring scanout from stale fd %d", scanout.fd);
+        return;
+    }
+
+    if (read(scanout.fd, &iosurfaceid, sizeof(iosurfaceid)) != sizeof(iosurfaceid)) {
+        SPICE_DEBUG("[CocoaSpice] Failed to read scanout fd: %d", scanout.fd);
+        perror("read");
         return;
         return;
     }
     }
-    
     if ((iosurface = IOSurfaceLookup(iosurfaceid)) == NULL) {
     if ((iosurface = IOSurfaceLookup(iosurfaceid)) == NULL) {
         SPICE_DEBUG("[CocoaSpice] Failed to lookup surface: %d", iosurfaceid);
         SPICE_DEBUG("[CocoaSpice] Failed to lookup surface: %d", iosurfaceid);
         return;
         return;