Package: libdbus-c++-1-0v5
Version: 0.9.0-8+b1
Tags: upstream patch
Severity: normal

Dear Maintainer,

Sometimes I'm getting a deadlock in dbus-c++ while debugging my application 
under gdb.

It happens when I interrupt the program when DBus request is already sent, but 
no reply received yet.
Then I'm debugging something for 25+ sec (so dbus timeout expires), continue 
execution and get a deadlock in a dbus-c++ dispatcher thread.
It happens for me only during gdb sessions. If I delay the reply on a DBus 
server side, different branch of logic is used by DBus and deadlock doesn't 
occur.

Backtrace of the deadlock:

(gdb) thread 4
[Switching to thread 4 (Thread 0xab721b40 (LWP 20192))]
#0  0xb7fd9d39 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fd9d39 in __kernel_vsyscall ()
#1  0xb3e0bde2 in __lll_lock_wait () from /lib/i386-linux-gnu/libpthread.so.0
#2  0xb3e0592e in pthread_mutex_lock () from /lib/i386-linux-gnu/libpthread.so.0
#3  0xb72917c8 in DBus::DefaultMutex::lock (this=0x5deb2d2c) at 
eventloop.cpp:104
#4  0xb7291c8a in DBus::DefaultTimeout::~DefaultTimeout (this=0x7a74a9e8, 
__in_chrg=<optimized out>) at eventloop.cpp:59
#5  0xb72933ce in DBus::BusTimeout::~BusTimeout (this=0x7a74a9e0, 
__in_chrg=<optimized out>) at ../include/dbus-c++/eventloop-integration.h:44
#6  DBus::BusTimeout::~BusTimeout (this=0x7a74a9e0, __in_chrg=<optimized out>) 
at ../include/dbus-c++/eventloop-integration.h:44
#7  0xb724dc43 in _dbus_timeout_list_remove_timeout (timeout_list=0x5df1b710, 
timeout=0x7a73e170) at ../../../dbus/dbus-timeout.c:347
#8  0xb723814a in protected_change_timeout (enabled=0, toggle_function=0x0, 
remove_function=<optimized out>, add_function=0x0, timeout=<optimized out>, 
connection=0x5df1cef8) at ../../../dbus/dbus-connection.c:841
#9  _dbus_connection_remove_timeout_unlocked (timeout=<optimized out>, 
connection=0x5df1cef8) at ../../../dbus/dbus-connection.c:888
#10 reply_handler_timeout (data=0x7a73ddd0) at 
../../../dbus/dbus-connection.c:3344
#11 0xb7290bbb in DBus::Timeout::handle (this=0x7a74a9e0) at dispatcher.cpp:58
#12 0xb729288d in DBus::BusDispatcher::timeout_expired (this=0x5deb2ce0, 
et=...) at eventloop-integration.cpp:201
#13 0xb7291b52 in DBus::Slot<void, DBus::DefaultTimeout&>::operator() 
(param=..., this=<optimized out>) at ../include/dbus-c++/util.h:240
#14 DBus::DefaultMainLoop::dispatch (this=0x5deb2d20) at eventloop.cpp:221
#15 0xb7292610 in DBus::BusDispatcher::enter (this=0x5deb2ce0) at 
eventloop-integration.cpp:100
...

DBus requests are sent from another thread, but it is not participating in the 
deadlock.

Deadlock happens in a dispatcher thread itself, which tries to lock the same 
non-recursive mutex it already holds: DefaultMainLoop::_mutex_t.

Deadlock happens in DBus::DefaultMainLoop::dispatch() in the following code:
  _mutex_t.lock();

  ti = _timeouts.begin();

  while (ti != _timeouts.end())
  {
    DefaultTimeouts::iterator tmp = ti;
    ++tmp;

    if ((*ti)->enabled() && now_millis >= (*ti)->_expiration)
    {
      (*ti)->expired(*(*ti));

      if ((*ti)->_repeat)
      {
        (*ti)->_expiration = now_millis + (*ti)->_interval;
      }

    }

    ti = tmp;
  }

  _mutex_t.unlock();

It locks _mutex_t, then calls "(ti)->expired((*ti));" which just deletes the 
timeout,
and tries to lock _mutex_t again in DefaultTimeout destructor:
DefaultTimeout::~DefaultTimeout()
{
  _disp->_mutex_t.lock();
  _disp->_timeouts.remove(this);
  _disp->_mutex_t.unlock();
}

It results in a deadlock by one thread on a non-recursive mutex.
Exactly the same problem is also described here: 
https://sourceforge.net/p/dbus-cplusplus/mailman/message/28745127/

I've tried making DefaultMainLoop::_mutex_t recursive, and it fixed the problem.

Can you please apply this patch?

Patch:

--- eventloop.cpp   2020-04-06 12:26:06.902743512 +0300
+++ NEW_eventloop.cpp   2020-04-06 12:26:00.838743134 +0300
@@ -110,6 +110,7 @@
}

DefaultMainLoop::DefaultMainLoop() :
+  _mutex_t(true),
   _mutex_w(true)
{
}


-- System Information:
Debian Release: 9.12
  APT prefers oldstable
  APT policy: (500, 'oldstable')
Architecture: i386 (i686)

Kernel: Linux 4.19.0-0.bpo.6-686-pae (SMP w/2 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968), LANGUAGE=C 
(charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages libdbus-c++-1-0v5 depends on:
ii  libc6         2.24-11+deb9u4
ii  libdbus-1-3   1.10.28-0+deb9u1
ii  libecore1     1.8.6-2.5+b2
ii  libgcc1       1:6.3.0-18+deb9u1
ii  libglib2.0-0  2.50.3-2+deb9u2
ii  libstdc++6    6.3.0-18+deb9u1

libdbus-c++-1-0v5 recommends no packages.

libdbus-c++-1-0v5 suggests no packages.

-- no debconf information

Reply via email to