[vlc-devel] [PATCH] dbus: don't spam dbus events

Thomas Guillem thomas at gllm.fr
Thu Feb 8 16:51:18 CET 2018


Wait 100ms before sending new events and drop identical events.

This fixes global Desktop freeze (happening on Gnome Shell with Debian stable)
when playing some files that update metadatas too much. This can also happen
when the playlist fail to open a lot of files in a row.
---
 modules/control/dbus/dbus.c | 79 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 66 insertions(+), 13 deletions(-)

diff --git a/modules/control/dbus/dbus.c b/modules/control/dbus/dbus.c
index 484195a7c6..77923daa02 100644
--- a/modules/control/dbus/dbus.c
+++ b/modules/control/dbus/dbus.c
@@ -75,6 +75,7 @@
 #define DBUS_INSTANCE_ID_PREFIX "instance"
 
 #define SEEK_THRESHOLD 1000 /* µsec */
+#define EVENTS_DELAY INT64_C(100000) /* 100 ms */
 
 /*****************************************************************************
  * Local prototypes.
@@ -768,6 +769,8 @@ static void *Run( void *data )
 
     int canc = vlc_savecancel();
 
+    mtime_t events_last_date = VLC_TS_INVALID;
+    int events_poll_timeout = -1;
     for( ;; )
     {
         vlc_mutex_lock( &p_sys->lock );
@@ -783,6 +786,8 @@ static void *Run( void *data )
 
         /* thread cancellation is allowed while the main loop sleeps */
         vlc_restorecancel( canc );
+        if( timeout == -1 )
+            timeout = events_poll_timeout;
 
         while (poll(fds, i_fds, timeout) == -1)
         {
@@ -822,18 +827,43 @@ static void *Run( void *data )
 
         /* Get the list of events to process */
         size_t i_events = vlc_array_count( &p_sys->events );
-        callback_info_t* p_info[i_events ? i_events : 1];
-        for( size_t i = 0; i < i_events; i++ )
+        callback_info_t** pp_info = NULL;
+
+        if( i_events > 0 )
         {
-            p_info[i] = vlc_array_item_at_index( &p_sys->events, i );
+            mtime_t now = mdate();
+            if( now - events_last_date > EVENTS_DELAY )
+            {
+                /* Send events every EVENTS_DELAY */
+                events_last_date = now;
+                events_poll_timeout = -1;
+
+                pp_info = vlc_alloc( i_events, sizeof(*pp_info) );
+                if( pp_info )
+                {
+                    for( size_t i = 0; i < i_events; i++ )
+                        pp_info[i] = vlc_array_item_at_index( &p_sys->events, i );
+                    vlc_array_clear( &p_sys->events );
+                }
+            }
+            else if( events_poll_timeout == -1 )
+            {
+                /* Request poll to wake up in order to send these events after
+                 * some delay */
+                events_poll_timeout = ( EVENTS_DELAY - ( now - events_last_date ) ) / 1000;
+            }
         }
-
-        vlc_array_clear( &p_sys->events );
+        else /* No events: clear timeout */
+            events_poll_timeout = -1;
 
         /* now we can release the lock and process what's pending */
         vlc_mutex_unlock( &p_intf->p_sys->lock );
 
-        ProcessEvents( p_intf, p_info, i_events );
+        if( pp_info )
+        {
+            ProcessEvents( p_intf, pp_info, i_events );
+            free( pp_info );
+        }
         ProcessWatches( p_intf, p_watches, i_watches, fds, i_fds );
 
         DispatchDBusMessages( p_intf );
@@ -852,6 +882,29 @@ static void   wakeup_main_loop( void *p_data )
                  vlc_strerror_c(errno) );
 }
 
+static bool add_event_locked( intf_thread_t *p_intf, callback_info_t *p_info )
+{
+    if( !p_info->signal )
+    {
+        free( p_info );
+        return false;
+    }
+
+    for( size_t i = 0; i < vlc_array_count( &p_intf->p_sys->events ); ++ i )
+    {
+        callback_info_t *oldinfo =
+            vlc_array_item_at_index( &p_intf->p_sys->events, i );
+        if( p_info->signal == oldinfo->signal )
+        {
+            free( p_info );
+            return false;
+        }
+    }
+
+    vlc_array_append( &p_intf->p_sys->events, p_info );
+    return true;
+}
+
 /* Flls a callback_info_t data structure in response
  * to an "intf-event" input event.
  *
@@ -941,13 +994,11 @@ static int InputCallback( vlc_object_t *p_this, const char *psz_var,
         p_sys->i_playing_state = i_state;
         p_info->signal = SIGNAL_STATE;
     }
-    if( p_info->signal )
-        vlc_array_append_or_abort( &p_sys->events, p_info );
-    else
-        free( p_info );
+    bool added = add_event_locked( p_intf, p_info );
     vlc_mutex_unlock( &p_intf->p_sys->lock );
 
-    wakeup_main_loop( p_intf );
+    if( added )
+        wakeup_main_loop( p_intf );
 
     (void)psz_var;
     (void)oldval;
@@ -1003,10 +1054,12 @@ static int AllCallback( vlc_object_t *p_this, const char *psz_var,
     // Append the event
     *p_info = info;
     vlc_mutex_lock( &p_intf->p_sys->lock );
-    vlc_array_append_or_abort( &p_intf->p_sys->events, p_info );
+    bool added = add_event_locked( p_intf, p_info );
     vlc_mutex_unlock( &p_intf->p_sys->lock );
 
-    wakeup_main_loop( p_intf );
+    if( added )
+        wakeup_main_loop( p_intf );
+
     (void) p_this;
     return VLC_SUCCESS;
 }
-- 
2.11.0



More information about the vlc-devel mailing list