Fixed #3423: Process xevents when in reconnect mode.
authorArmin Novak <armin.novak@thincast.com>
Mon, 24 Sep 2018 14:24:32 +0000 (16:24 +0200)
committerArmin Novak <armin.novak@thincast.com>
Mon, 24 Sep 2018 14:24:32 +0000 (16:24 +0200)
Fixed crashes due to unloaded disp channel in reconnect mode.

client/X11/xf_client.c
client/X11/xf_disp.c
client/X11/xf_event.c
client/common/client.c
include/freerdp/client.h

index c7700a8..a357bef 100644 (file)
@@ -1413,6 +1413,27 @@ static DWORD WINAPI xf_input_thread(LPVOID arg)
        return 0;
 }
 
+static BOOL handle_window_events(freerdp* instance)
+{
+       rdpSettings* settings;
+
+       if (!instance || !instance->settings)
+               return FALSE;
+
+       settings = instance->settings;
+
+       if (!settings->AsyncInput)
+       {
+               if (!xf_process_x_events(instance))
+               {
+                       WLog_INFO(TAG, "Closed from X11");
+                       return FALSE;
+               }
+       }
+
+       return TRUE;
+}
+
 /** Main loop for the rdp connection.
 *  It will be run from the thread's entry point (thread_func()).
 *  It initiates the connection, and will continue to run until the session ends,
@@ -1548,7 +1569,7 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
                {
                        if (!freerdp_check_event_handles(context))
                        {
-                               if (client_auto_reconnect(instance))
+                               if (client_auto_reconnect_ex(instance, handle_window_events))
                                        continue;
                                else
                                {
@@ -1567,14 +1588,8 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
                        }
                }
 
-               if (!settings->AsyncInput)
-               {
-                       if (!xf_process_x_events(instance))
-                       {
-                               WLog_INFO(TAG, "Closed from X11");
-                               break;
-                       }
-               }
+               if (!handle_window_events(instance))
+                       break;
 
                if ((status != WAIT_TIMEOUT) && (waitStatus == WAIT_OBJECT_0))
                {
index fdf8eae..ee1dec1 100644 (file)
@@ -58,6 +58,10 @@ static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, in
 static BOOL xf_disp_settings_changed(xfDispContext* xfDisp)
 {
        rdpSettings* settings;
+
+       if (!xfDisp || !xfDisp->xfc || !xfDisp->xfc->context.settings)
+               return FALSE;
+
        settings = xfDisp->xfc->context.settings;
 
        if (xfDisp->lastSentWidth != xfDisp->targetWidth)
@@ -83,7 +87,16 @@ static BOOL xf_disp_settings_changed(xfDispContext* xfDisp)
 
 static BOOL xf_update_last_sent(xfDispContext* xfDisp)
 {
-       rdpSettings* settings = xfDisp->xfc->context.settings;
+       rdpSettings* settings;
+
+       if (!xfDisp || !xfDisp->xfc)
+               return FALSE;
+
+       settings = xfDisp->xfc->context.settings;
+
+       if (!settings)
+               return FALSE;
+
        xfDisp->lastSentWidth = xfDisp->targetWidth;
        xfDisp->lastSentHeight = xfDisp->targetHeight;
        xfDisp->lastSentDesktopOrientation = settings->DesktopOrientation;
@@ -96,8 +109,17 @@ static BOOL xf_update_last_sent(xfDispContext* xfDisp)
 static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
 {
        DISPLAY_CONTROL_MONITOR_LAYOUT layout;
-       xfContext* xfc = xfDisp->xfc;
-       rdpSettings* settings = xfc->context.settings;
+       xfContext* xfc;
+       rdpSettings* settings;
+
+       if (!xfDisp || !xfDisp->xfc)
+               return FALSE;
+
+       xfc = xfDisp->xfc;
+       settings = xfc->context.settings;
+
+       if (!settings)
+               return FALSE;
 
        if (!xfDisp->activated)
                return TRUE;
@@ -129,7 +151,8 @@ static BOOL xf_disp_sendResize(xfDispContext* xfDisp)
                layout.PhysicalWidth = xfDisp->targetWidth;
                layout.PhysicalHeight = xfDisp->targetHeight;
 
-               if (xfc->disp->SendMonitorLayout(xfc->disp, 1, &layout) != CHANNEL_RC_OK)
+               if (IFCALLRESULT(CHANNEL_RC_OK, xfc->disp->SendMonitorLayout, xfc->disp, 1,
+                                &layout) != CHANNEL_RC_OK)
                        return FALSE;
        }
 
@@ -288,17 +311,30 @@ static UINT xf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, in
                layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor;
        }
 
-       ret = disp->SendMonitorLayout(disp, nmonitors, layouts);
+       ret = IFCALLRESULT(CHANNEL_RC_OK, disp->SendMonitorLayout, disp, nmonitors, layouts);
        free(layouts);
        return ret;
 }
 
 BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event)
 {
-       xfDispContext* xfDisp = xfc->xfDisp;
-       rdpSettings* settings = xfc->context.settings;
+       xfDispContext* xfDisp;
+       rdpSettings* settings;
        UINT32 maxWidth, maxHeight;
 
+       if (!xfc || !event)
+               return FALSE;
+
+       xfDisp = xfc->xfDisp;
+
+       if (!xfDisp)
+               return FALSE;
+
+       settings = xfc->context.settings;
+
+       if (!settings)
+               return FALSE;
+
        if (!xfDisp->haveXRandr)
                return TRUE;
 
@@ -316,7 +352,12 @@ BOOL xf_disp_handle_xevent(xfContext* xfc, XEvent* event)
 
 BOOL xf_disp_handle_configureNotify(xfContext* xfc, int width, int height)
 {
-       xfDispContext* xfDisp = xfc->xfDisp;
+       xfDispContext* xfDisp;
+
+       if (!xfc || !xfc->disp)
+               return FALSE;
+
+       xfDisp = xfc->xfDisp;
        xfDisp->targetWidth = width;
        xfDisp->targetHeight = height;
        return xf_disp_sendResize(xfDisp);
index 01449d2..25666e5 100644 (file)
@@ -1103,7 +1103,7 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
                        break;
 
                default:
-                       if (settings->SupportDisplayControl && xfc->xfDisp)
+                       if (settings->SupportDisplayControl)
                                xf_disp_handle_xevent(xfc, event);
 
                        break;
index 0fda231..06146a4 100644 (file)
@@ -555,6 +555,11 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
 
 BOOL client_auto_reconnect(freerdp* instance)
 {
+       return client_auto_reconnect_ex(instance, NULL);
+}
+
+BOOL client_auto_reconnect_ex(freerdp* instance, BOOL(*window_events)(freerdp* instance))
+{
        UINT32 maxRetries;
        UINT32 numRetries = 0;
        rdpSettings* settings;
@@ -581,6 +586,8 @@ BOOL client_auto_reconnect(freerdp* instance)
        /* Perform an auto-reconnect. */
        while (TRUE)
        {
+               UINT32 x;
+
                /* Quit retrying if max retries has been exceeded */
                if ((maxRetries > 0) && (numRetries++ >= maxRetries))
                {
@@ -593,7 +600,13 @@ BOOL client_auto_reconnect(freerdp* instance)
                if (freerdp_reconnect(instance))
                        return TRUE;
 
-               Sleep(5000);
+               for (x = 0; x < 50; x++)
+               {
+                       if (!IFCALLRESULT(TRUE, window_events, instance))
+                               return FALSE;
+
+                       Sleep(100);
+               }
        }
 
        WLog_ERR(TAG, "Maximum reconnect retries exceeded");
index b5e78a9..c6267bc 100644 (file)
@@ -113,6 +113,8 @@ FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const
         const char* old_subject, const char* old_issuer,
         const char* old_fingerprint);
 FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
+FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
+        BOOL(*window_events)(freerdp* instance));
 
 #ifdef __cplusplus
 }