[nautilus] progress-info: avoid races



commit 27783cc8c234e533fb4ec4401efe3b41238220c7
Author: Carlos Soriano <csoriano gnome org>
Date:   Wed Nov 23 15:04:39 2016 +0100

    progress-info: avoid races
    
    We were not checking whether the operations was aborted from the user
    side when setting the details,so that could make a race and the info
    thread setting the details to canceled and the operation thread setting
    the details too afterwards before realizing the operations was canceled.
    
    To fix it, always check whether the info progress was canceled or not.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=775094

 src/nautilus-progress-info.c |   82 +++++++++++++++++++++++------------------
 1 files changed, 46 insertions(+), 36 deletions(-)
---
diff --git a/src/nautilus-progress-info.c b/src/nautilus-progress-info.c
index 5a4c7d2..d8ac8d2 100644
--- a/src/nautilus-progress-info.c
+++ b/src/nautilus-progress-info.c
@@ -83,6 +83,11 @@ G_LOCK_DEFINE_STATIC (progress_info);
 
 G_DEFINE_TYPE (NautilusProgressInfo, nautilus_progress_info, G_TYPE_OBJECT)
 
+static void set_details (NautilusProgressInfo *info,
+                         const char           *details);
+static void set_status  (NautilusProgressInfo *info,
+                         const char           *status);
+
 static void
 nautilus_progress_info_finalize (GObject *object)
 {
@@ -309,7 +314,7 @@ set_details_in_thread (GTask                *task,
 {
     if (!g_cancellable_is_cancelled (cancellable))
     {
-        nautilus_progress_info_set_details (info, _("Canceled"));
+        set_details (info, _("Canceled"));
         G_LOCK (progress_info);
         info->cancel_at_idle = TRUE;
         g_timer_stop (info->progress_timer);
@@ -566,26 +571,32 @@ nautilus_progress_info_finish (NautilusProgressInfo *info)
     G_UNLOCK (progress_info);
 }
 
+static void
+set_status (NautilusProgressInfo *info,
+            const char           *status)
+{
+    g_free (info->status);
+    info->status = g_strdup (status);
+
+    info->changed_at_idle = TRUE;
+    queue_idle (info, FALSE);
+}
+
 void
 nautilus_progress_info_take_status (NautilusProgressInfo *info,
                                     char                 *status)
 {
     G_LOCK (progress_info);
 
-    if (g_strcmp0 (info->status, status) != 0)
+    if (g_strcmp0 (info->status, status) != 0 &&
+        !g_cancellable_is_cancelled (info->cancellable))
     {
-        g_free (info->status);
-        info->status = status;
-
-        info->changed_at_idle = TRUE;
-        queue_idle (info, FALSE);
-    }
-    else
-    {
-        g_free (status);
+        set_status (info, status);
     }
 
     G_UNLOCK (progress_info);
+
+    g_free (status);
 }
 
 void
@@ -594,18 +605,25 @@ nautilus_progress_info_set_status (NautilusProgressInfo *info,
 {
     G_LOCK (progress_info);
 
-    if (g_strcmp0 (info->status, status) != 0)
+    if (g_strcmp0 (info->status, status) != 0 &&
+        !g_cancellable_is_cancelled (info->cancellable))
     {
-        g_free (info->status);
-        info->status = g_strdup (status);
-
-        info->changed_at_idle = TRUE;
-        queue_idle (info, FALSE);
+        set_status (info, status);
     }
 
     G_UNLOCK (progress_info);
 }
 
+static void
+set_details (NautilusProgressInfo *info,
+             const char           *details)
+{
+    g_free (info->details);
+    info->details = g_strdup (details);
+
+    info->changed_at_idle = TRUE;
+    queue_idle (info, FALSE);
+}
 
 void
 nautilus_progress_info_take_details (NautilusProgressInfo *info,
@@ -613,20 +631,15 @@ nautilus_progress_info_take_details (NautilusProgressInfo *info,
 {
     G_LOCK (progress_info);
 
-    if (g_strcmp0 (info->details, details) != 0)
+    if (g_strcmp0 (info->details, details) != 0 &&
+        !g_cancellable_is_cancelled (info->cancellable))
     {
-        g_free (info->details);
-        info->details = details;
-
-        info->changed_at_idle = TRUE;
-        queue_idle (info, FALSE);
-    }
-    else
-    {
-        g_free (details);
+        set_details (info, details);
     }
 
     G_UNLOCK (progress_info);
+
+    g_free (details);
 }
 
 void
@@ -635,13 +648,10 @@ nautilus_progress_info_set_details (NautilusProgressInfo *info,
 {
     G_LOCK (progress_info);
 
-    if (g_strcmp0 (info->details, details) != 0)
+    if (g_strcmp0 (info->details, details) != 0 &&
+        !g_cancellable_is_cancelled (info->cancellable))
     {
-        g_free (info->details);
-        info->details = g_strdup (details);
-
-        info->changed_at_idle = TRUE;
-        queue_idle (info, FALSE);
+        set_details (info, details);
     }
 
     G_UNLOCK (progress_info);
@@ -688,9 +698,9 @@ nautilus_progress_info_set_progress (NautilusProgressInfo *info,
 
     G_LOCK (progress_info);
 
-    if (info->activity_mode ||     /* emit on switch from activity mode */
-        fabs (current_percent - info->progress) > 0.005     /* Emit on change of 0.5 percent */
-        )
+    if ((info->activity_mode ||     /* emit on switch from activity mode */
+        fabs (current_percent - info->progress) > 0.005) &&     /* Emit on change of 0.5 percent */
+        !g_cancellable_is_cancelled (info->cancellable))
     {
         info->activity_mode = FALSE;
         info->progress = current_percent;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]