Fixed surface locking for shadow server.
authorakallabeth <akallabeth@posteo.net>
Wed, 27 May 2020 08:01:04 +0000 (10:01 +0200)
committerakallabeth <akallabeth@posteo.net>
Tue, 16 Jun 2020 09:42:55 +0000 (11:42 +0200)
(cherry picked from commit a38d6c53a62cdea302fbeb4e466bce22c006d20c)

server/shadow/Mac/mac_shadow.c
server/shadow/X11/x11_shadow.c
server/shadow/shadow_client.c

index 0532329..6dd3ba1 100644 (file)
@@ -370,6 +370,7 @@ static void (^mac_capture_stream_handler)(
   int width;
   int height;
   int nSrcStep;
+  BOOL empty;
   BYTE* pSrcData;
   RECTANGLE_16 surfaceRect;
   const RECTANGLE_16* extents;
@@ -381,14 +382,17 @@ static void (^mac_capture_stream_handler)(
   if (count < 1)
          return;
 
+  EnterCriticalSection(&(surface->lock));
   mac_shadow_capture_get_dirty_region(subsystem);
   surfaceRect.left = 0;
   surfaceRect.top = 0;
   surfaceRect.right = surface->width;
   surfaceRect.bottom = surface->height;
   region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
+  empty = region16_is_empty(&(surface->invalidRegion));
+  LeaveCriticalSection(&(surface->lock));
 
-  if (!region16_is_empty(&(surface->invalidRegion)))
+  if (!empty)
   {
          extents = region16_extents(&(surface->invalidRegion));
          x = extents->left;
@@ -410,13 +414,12 @@ static void (^mac_capture_stream_handler)(
                                         pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x, y, NULL,
                                         FREERDP_FLIP_NONE);
          }
+         LeaveCriticalSection(&(surface->lock));
 
          IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
          ArrayList_Lock(server->clients);
          count = ArrayList_Count(server->clients);
-         EnterCriticalSection(&(surface->lock));
          shadow_subsystem_frame_update(&subsystem->common);
-         LeaveCriticalSection(&(surface->lock));
 
          if (count == 1)
          {
@@ -430,7 +433,9 @@ static void (^mac_capture_stream_handler)(
          }
 
          ArrayList_Unlock(server->clients);
+         EnterCriticalSection(&(surface->lock));
          region16_clear(&(surface->invalidRegion));
+         LeaveCriticalSection(&(surface->lock));
   }
 
   if (status != kCGDisplayStreamFrameStatusFrameComplete)
index 98cf44d..e48df01 100644 (file)
@@ -736,6 +736,7 @@ static int x11_shadow_error_handler_for_capture(Display* display, XErrorEvent* e
 
 static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
 {
+       int rc = 0;
        int count;
        int status;
        int x, y;
@@ -753,10 +754,13 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
        if (count < 1)
                return 1;
 
+       EnterCriticalSection(&surface->lock);
        surfaceRect.left = 0;
        surfaceRect.top = 0;
        surfaceRect.right = surface->width;
        surfaceRect.bottom = surface->height;
+       LeaveCriticalSection(&surface->lock);
+
        XLockDisplay(subsystem->display);
        /*
         * Ignore BadMatch error during image capture. The screen size may be
@@ -769,15 +773,26 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
                image = subsystem->fb_image;
                XCopyArea(subsystem->display, subsystem->root_window, subsystem->fb_pixmap,
                          subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
+
+               EnterCriticalSection(&surface->lock);
                status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
                                                surface->height, (BYTE*)&(image->data[surface->width * 4]),
                                                image->bytes_per_line, &invalidRect);
+               LeaveCriticalSection(&surface->lock);
        }
        else
        {
+               EnterCriticalSection(&surface->lock);
                image = XGetImage(subsystem->display, subsystem->root_window, surface->x, surface->y,
                                  surface->width, surface->height, AllPlanes, ZPixmap);
 
+               if (image)
+               {
+                       status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
+                                                       surface->height, (BYTE*)image->data,
+                                                       image->bytes_per_line, &invalidRect);
+               }
+               LeaveCriticalSection(&surface->lock);
                if (!image)
                {
                        /*
@@ -786,10 +801,6 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
                         */
                        goto fail_capture;
                }
-
-               status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
-                                               surface->height, (BYTE*)image->data, image->bytes_per_line,
-                                               &invalidRect);
        }
 
        /* Restore the default error handler */
@@ -799,25 +810,32 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
 
        if (status)
        {
+               BOOL empty;
+               EnterCriticalSection(&surface->lock);
                region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
                region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
+               empty = region16_is_empty(&(surface->invalidRegion));
+               LeaveCriticalSection(&surface->lock);
 
-               if (!region16_is_empty(&(surface->invalidRegion)))
+               if (!empty)
                {
+                       BOOL success;
+                       EnterCriticalSection(&surface->lock);
                        extents = region16_extents(&(surface->invalidRegion));
                        x = extents->left;
                        y = extents->top;
                        width = extents->right - extents->left;
                        height = extents->bottom - extents->top;
-
-                       if (!freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width,
-                                               height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32,
-                                               image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE))
+                       success = freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y,
+                                                    width, height, (BYTE*)image->data, PIXEL_FORMAT_BGRX32,
+                                                    image->bytes_per_line, x, y, NULL, FREERDP_FLIP_NONE);
+                       LeaveCriticalSection(&surface->lock);
+                       if (!success)
                                goto fail_capture;
 
                        // x11_shadow_blend_cursor(subsystem);
                        count = ArrayList_Count(server->clients);
-                       shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem);
+                       shadow_subsystem_frame_update(&subsystem->common);
 
                        if (count == 1)
                        {
@@ -829,23 +847,25 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
                                            shadow_encoder_preferred_fps(client->encoder);
                        }
 
+                       EnterCriticalSection(&surface->lock);
                        region16_clear(&(surface->invalidRegion));
+                       LeaveCriticalSection(&surface->lock);
                }
        }
 
-       if (!subsystem->use_xshm)
-               XDestroyImage(image);
-
-       return 1;
+       rc = 1;
 fail_capture:
-
        if (!subsystem->use_xshm && image)
                XDestroyImage(image);
 
-       XSetErrorHandler(NULL);
-       XSync(subsystem->display, False);
-       XUnlockDisplay(subsystem->display);
-       return 0;
+       if (rc != 1)
+       {
+               XSetErrorHandler(NULL);
+               XSync(subsystem->display, False);
+               XUnlockDisplay(subsystem->display);
+       }
+
+       return rc;
 }
 
 static int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage* message)
index f32f649..86bc3fc 100644 (file)
@@ -1331,12 +1331,12 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF
        region16_copy(&invalidRegion, &(client->invalidRegion));
        region16_clear(&(client->invalidRegion));
        LeaveCriticalSection(&(client->lock));
+
+       EnterCriticalSection(&surface->lock);
        rects = region16_rects(&(surface->invalidRegion), &numRects);
 
        for (index = 0; index < numRects; index++)
-       {
                region16_union_rect(&invalidRegion, &invalidRegion, &rects[index]);
-       }
 
        surfaceRect.left = 0;
        surfaceRect.top = 0;
@@ -1410,6 +1410,7 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF
        }
 
 out:
+       LeaveCriticalSection(&surface->lock);
        region16_uninit(&invalidRegion);
        return ret;
 }