diff --git a/include/sdbus-c++/IConnection.h b/include/sdbus-c++/IConnection.h index 8030a1a..3d091df 100644 --- a/include/sdbus-c++/IConnection.h +++ b/include/sdbus-c++/IConnection.h @@ -64,6 +64,10 @@ namespace sdbus { */ struct PollData { + /*! + * The read fd to be monitored by the event loop. + */ + int event_fd; /*! * The read fd to be monitored by the event loop. */ diff --git a/src/Connection.cpp b/src/Connection.cpp index d235ed1..b901a09 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -75,11 +75,16 @@ Connection::Connection(std::unique_ptr&& interface, pseudo_bus_t) , bus_(openPseudoBus()) { assert(iface_ != nullptr); + eventFd_.fd = eventfd(0, 0); + assert(eventFd_.fd >= 0); } Connection::~Connection() { Connection::leaveEventLoop(); + if (0 <= eventFd_.fd) { + close(eventFd_.fd); + } } void Connection::requestName(const std::string& name) @@ -141,7 +146,7 @@ Connection::PollData Connection::getEventLoopPollData() const auto r = iface_->sd_bus_get_poll_data(bus_.get(), &pollData); SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus poll data", -r); - return {pollData.fd, pollData.events, pollData.timeout_usec}; + return {eventFd_.fd, pollData.fd, pollData.events, pollData.timeout_usec}; } const ISdBus& Connection::getSdBusInterface() const @@ -445,6 +450,11 @@ void Connection::notifyEventLoopToExit() const notifyEventLoop(loopExitFd_.fd); } +void Connection::notifyEventLoop() const +{ + notifyEventLoop(eventFd_.fd); +} + void Connection::notifyEventLoopNewTimeout() const { // The extra notifications for new timeouts are only needed if calls are made asynchronously to the event loop. diff --git a/src/Connection.h b/src/Connection.h index 445c915..46474cc 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -139,6 +139,7 @@ namespace sdbus::internal { void notifyEventLoop(int fd) const; void notifyEventLoopToExit() const; void clearEventLoopNotification(int fd) const; + void notifyEventLoop() const override; void notifyEventLoopNewTimeout() const override; private: diff --git a/src/IConnection.h b/src/IConnection.h index 74b7832..67bee41 100644 --- a/src/IConnection.h +++ b/src/IConnection.h @@ -90,6 +90,7 @@ namespace sdbus::internal { , sd_bus_message_handler_t callback , void* userData ) = 0; + virtual void notifyEventLoop() const = 0; virtual void notifyEventLoopNewTimeout() const = 0; virtual MethodReply tryCallMethodSynchronously(const MethodCall& message, uint64_t timeout) = 0; }; diff --git a/src/Message.cpp b/src/Message.cpp index 696df64..e80b2a0 100644 --- a/src/Message.cpp +++ b/src/Message.cpp @@ -782,6 +782,10 @@ MethodReply MethodCall::sendWithReply(uint64_t timeout) const SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r); + // Force event loop to re-enter processing to handle queued messages + SDBUS_THROW_ERROR_IF(connection_ == nullptr, "Invalid use of MethodCall API", ENOTSUP); + connection_->notifyEventLoop(); + return Factory::create(sdbusReply, sdbus_, adopt_message); } @@ -790,6 +794,10 @@ MethodReply MethodCall::sendWithNoReply() const auto r = sdbus_->sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr); SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method with no reply", -r); + // Force event loop to re-enter processing to handle queued messages + SDBUS_THROW_ERROR_IF(connection_ == nullptr, "Invalid use of MethodCall API", ENOTSUP); + connection_->notifyEventLoop(); + return Factory::create(); // No reply }