A slightly better DbusIpcThread

...that doesn't burn CPU by always directly returning again from a
dbus_connection_read_write call with zero timeout.  But still doesn't look like
it uses DBus the way it's intended to.  Help appreciated.

Change-Id: I0d130adfb921409a27a847053b0b3646dc566a86
diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx
index 31635e8..3990944 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -46,6 +46,7 @@
#include <rtl/process.h>
#include <tools/getprocessworkingdir.hxx>

#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <memory>
@@ -405,20 +406,17 @@ struct DbusConnectionHolder {
        connection(theConnection)
    {}

    ~DbusConnectionHolder() { clear(); }
    DbusConnectionHolder(DbusConnectionHolder && other): connection(nullptr)
    { std::swap(connection, other.connection); }

    void clear() {
    ~DbusConnectionHolder() {
        if (connection != nullptr) {
            dbus_connection_close(connection);
            dbus_connection_unref(connection);
        }
        connection = nullptr;
    }

    DBusConnection * connection;

private:
    DbusConnectionHolder(DbusConnectionHolder &) = delete;
    void operator =(DbusConnectionHolder) = delete;
};

struct DbusMessageHolder {
@@ -447,8 +445,8 @@ public:
    static RequestHandler::Status enable(rtl::Reference<IpcThread> * thread);

private:
    explicit DbusIpcThread(DBusConnection * connection):
        IpcThread("DbusIPC"), connection_(connection)
    explicit DbusIpcThread(DbusConnectionHolder && connection):
        IpcThread("DbusIPC"), connection_(std::move(connection))
    {}

    virtual ~DbusIpcThread() {}
@@ -469,12 +467,13 @@ RequestHandler::Status DbusIpcThread::enable(rtl::Reference<IpcThread> * thread)
    }
    DBusError e;
    dbus_error_init(&e);
    DbusConnectionHolder con(dbus_bus_get(DBUS_BUS_SESSION, &e));
    DbusConnectionHolder con(dbus_bus_get_private(DBUS_BUS_SESSION, &e));
    assert((con.connection == nullptr) == bool(dbus_error_is_set(&e)));
    if (con.connection == nullptr) {
        SAL_WARN(
            "desktop.app",
            "dbus_bus_get failed with: " << e.name << ": " << e.message);
            "dbus_bus_get_private failed with: " << e.name << ": "
                << e.message);
        dbus_error_free(&e);
        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
    }
@@ -492,8 +491,7 @@ RequestHandler::Status DbusIpcThread::enable(rtl::Reference<IpcThread> * thread)
            dbus_error_free(&e);
            return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
            *thread = new DbusIpcThread(con.connection);
            con.connection = nullptr;
            *thread = new DbusIpcThread(std::move(con));
            return RequestHandler::IPC_STATUS_OK;
        case DBUS_REQUEST_NAME_REPLY_EXISTS:
            {
@@ -569,12 +567,17 @@ void DbusIpcThread::execute()
                break;
            }
        }
        dbus_connection_read_write(connection_.connection, 0);
        dbus_connection_read_write_dispatch(connection_.connection, -1);
        DbusMessageHolder msg(
            dbus_connection_pop_message(connection_.connection));
        if (msg.message == nullptr) {
            continue;
        }
        if (dbus_message_is_method_call(
                msg.message, "org.libreoffice.LibreOfficeIpcIfc0", "Close"))
        {
            break;
        }
        if (!dbus_message_is_method_call(
                msg.message, "org.libreoffice.LibreOfficeIpcIfc0", "Execute"))
        {
@@ -622,6 +625,37 @@ void DbusIpcThread::close() {
    assert(connection_.connection != nullptr);
    DBusError e;
    dbus_error_init(&e);
    {
        // Let DbusIpcThread::execute return from dbus_connection_read_write;
        // for now, just abort on failure (the process would otherwise block,
        // with DbusIpcThread::execute hanging in dbus_connection_read_write);
        // this apparently needs a more DBus-y design anyway:
        DbusConnectionHolder con(dbus_bus_get_private(DBUS_BUS_SESSION, &e));
        assert((con.connection == nullptr) == bool(dbus_error_is_set(&e)));
        if (con.connection == nullptr) {
            SAL_WARN(
                "desktop.app",
                "dbus_bus_get_private failed with: " << e.name << ": "
                    << e.message);
            dbus_error_free(&e);
            std::abort();
        }
        DbusMessageHolder msg(
            dbus_message_new_method_call(
                "org.libreoffice.LibreOfficeIpc0",
                "/org/libreoffice/LibreOfficeIpc0",
                "org.libreoffice.LibreOfficeIpcIfc0", "Close"));
        if (msg.message == nullptr) {
            SAL_WARN("desktop.app", "dbus_message_new_method_call failed");
            std::abort();
        }
        if (!dbus_connection_send(con.connection, msg.message, nullptr))
        {
            SAL_WARN("desktop.app", "dbus_connection_send failed");
            std::abort();
        }
        dbus_connection_flush(con.connection);
    }
    int n = dbus_bus_release_name(
        connection_.connection, "org.libreoffice.LibreOfficeIpc0", &e);
    assert((n == -1) == bool(dbus_error_is_set(&e)));
@@ -644,7 +678,6 @@ void DbusIpcThread::close() {
    default:
        for (;;) std::abort();
    }
    connection_.clear();
}

#endif