diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2009-03-27 17:10:36 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2009-03-27 20:55:28 (GMT) |
commit | b410a39fad176593ed75b742a486f8710c6ef60f (patch) | |
tree | b4559d7bb3335feb60c95cff37787900a66c9c69 | |
parent | ec24cf81e231974fde2bb4903a00e63abce6465b (diff) | |
download | Qt-b410a39fad176593ed75b742a486f8710c6ef60f.zip Qt-b410a39fad176593ed75b742a486f8710c6ef60f.tar.gz Qt-b410a39fad176593ed75b742a486f8710c6ef60f.tar.bz2 |
Fix crashes in D-Bus due to race conditions.
This happens in heavily threaded applications: libdbus-1 asks us to add
and remove timers (and watches, but those less often) from any thread.
Since QObject's model requires that timers and QSocketDescriptors be
added only in the object's own thread, we have to sync back to the main
thread.
However, since D-Bus keeps adding and removing the timers, we have to
keep a queue of timers to be added and that list is accessed by any
thread. Make sure that list is only accessed in locked conditions.
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 6 | ||||
-rw-r--r-- | src/dbus/qdbusthreaddebug_p.h | 7 |
2 files changed, 8 insertions, 5 deletions
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 7ed0cd5..674426b 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -137,6 +137,7 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) if (!q_dbus_timeout_get_enabled(timeout)) return true; + QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); if (QCoreApplication::instance() && QThread::currentThread() == d->thread()) { // correct thread return qDBusRealAddTimeout(d, timeout, q_dbus_timeout_get_interval(timeout)); @@ -152,7 +153,6 @@ static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data) static bool qDBusRealAddTimeout(QDBusConnectionPrivate *d, DBusTimeout *timeout, int ms) { - QDBusWatchAndTimeoutLocker locker(AddTimeoutAction, d); Q_ASSERT(d->timeouts.keys(timeout).isEmpty()); int timerId = d->startTimer(ms); @@ -1035,12 +1035,14 @@ void QDBusConnectionPrivate::customEvent(QEvent *e) QDBusLockerBase::BeforeDeliver, this); switch (ev->subtype) { - case QDBusConnectionCallbackEvent::AddTimeout: + case QDBusConnectionCallbackEvent::AddTimeout: { + QDBusWatchAndTimeoutLocker locker(RealAddTimeoutAction, this); while (!timeoutsPendingAdd.isEmpty()) { QPair<DBusTimeout *, int> entry = timeoutsPendingAdd.takeFirst(); qDBusRealAddTimeout(this, entry.first, entry.second); } break; + } case QDBusConnectionCallbackEvent::KillTimer: qDebug() << QThread::currentThread() << "RemoveTimeout: killing timer" << (ev->timerId & 0xffffff); diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h index 715bd6f..20d819f 100644 --- a/src/dbus/qdbusthreaddebug_p.h +++ b/src/dbus/qdbusthreaddebug_p.h @@ -92,9 +92,10 @@ enum ThreadAction { PendingCallBlockAction = 28, AddTimeoutAction = 50, - RemoveTimeoutAction = 51, - KillTimerAction = 52, - TimerEventAction = 53, + RealAddTimeoutAction = 51, + RemoveTimeoutAction = 52, + KillTimerAction = 58, + TimerEventAction = 59, AddWatchAction = 60, RemoveWatchAction = 61, ToggleWatchAction = 62, |