Since synchronous D-Bus calls are simplified in v2.0 and no more implemented in terms of an async call, the issue reported in #362 is no more relevant, and we can return to the simple boolean flag for indicating a finished call.
Signatures of callbacks async_reply_handler, signal_handler, message_handler and property_set_callback were modified to take input message objects by value, as opposed to non-const ref.
The callee assumes ownership of the message. This API is more idiomatic, more expressive, cleaner and safer. Move semantics is used to pass messages to the callback handlers. In some cases, this also improves performance.
In case a signal arrives during the `RequestName` or `ReleaseName` D-Bus call (which is a synchronous call), the signal may not be processed immediately, which is a bug. This is solved now by waking up the event loop.
* chore: Use std::exchange in UnixFd
This was suggested in code review for #376 .
* fix: Protect against UnixFd self-assignment
While self-assignment is rare, it is expected to be safe. Add a check
to prevent putting the object in an invalid state.
* fix: Improve hygiene around dup system call
- Don't try to call dup on a negative value.
- Check dup return code and throw if it fails, rather than returning an
empty UnixFd object.
* chore: Move UnixFd::close to Types.cpp
Minor convenience for applications: unistd.h doesn't have to be included
in the public header.
---------
Co-authored-by: David Reiss <dreiss@meta.com>
* Catch and process all exceptions (not just sdbus::Error) from callback handlers
* Unify handling of exceptions from all types of callbacks -- always set sd_bus_error and return a negative result number in case of exception
Although libsystemd logs (with DEBUG severity) all errors from such callback handlers (except method callback handler), it seems to be out of our control. One of handy sdbus-c++ features could be the ability for clients to install a log callback, which sdbus-c++ would call in case of exceptions flying from callback handlers. In case something doesn't work for clients (especially novices), they can first look into these logs.
This may be handy in common situations like ignored signals on client side because of the inadvertent mismatch between real signal signature and signal handler signature. Like here: #373. (Although in this specific case of signals, there is a solution with an additional const sdbus::Error* argument that would reveal such an error.)
* fix: Use-after-return in synchronous calls
This bug was introduced by c39bc637b8 and can be reproduced by
configuring with
cmake -S . -B build -DBUILD_TESTS=yes -DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_CXX_FLAGS="-Wno-error=deprecated-copy -fno-omit-frame-pointer -fsanitize=address -fsanitize-address-use-after-scope"
and running `cmake --buid build && cmake --build build -t test` or
`build/tests/sdbus-c++-integration-tests --gtest_filter=SdbusTestObject.HandlesCorrectlyABulkOfParallelServerSideAsyncMethods`
The issue is that `sdbus_async_reply_handler` can call `removeCall`, which
writes to `data->finished`, but `data` can point to the stack of
`sendMethodCallMessageAndWaitForReply`, which can return as soon as
`asyncCallData->callback` is called.
As a fix, I restored some of the logic removed in c39bc637b8.
Specifically, in `sdbus_async_reply_handler`, I make a copy of some data
from `asyncCallData` (a new `state` field instead of `slot`), and in the
`SCOPE_GUARD`, I don't call `removeCall` if the call was actually
synchronous.
* refactor: use enum class instead of int
---------
Co-authored-by: David Reiss <dreiss@meta.com>
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
* feat: add support for direct connections
* refactor: simplify a bit, change comments, extend tests
* fix: compiler warning about unused variable
* docs: add section on direct connections to the tutorial
---------
Co-authored-by: Maksim Fedyarov <m.fedyarov@omp.ru>
Co-authored-by: Stanislav Angelovič <stanislav.angelovic@protonmail.com>
* chore: don't use systemd headers with elogind
In file included from src/VTableUtils.c:27:
src/VTableUtils.h:30:10: fatal error: 'systemd/sd-bus.h' file not found
#include <systemd/sd-bus.h>
^~~~~~~~~~~~~~~~~~
* chore: add basu support
Similar to elogind but also supported on non-Linux.
* chore(tests): permit /var/lib/machine-id on non-systemd
https://github.com/elogind/elogind/commit/84fdc0fc61c1https://git.sr.ht/~emersion/basu/commit/8324e6729231
* chore(ci): add simple freebsd job
Mainly to cover libc++ and basu.
* chore(ci): explicitly pass CMAKE_INSTALL_PREFIX
Some sdbus-cpp tests require configuring system bus. However, Linux
testing relies on writing outside of prefix in order to affect current
system bus instance instead of launching a dedicated one.
* chore(tests): respect CMAKE_INSTALL_PREFIX for system bus config
DBus isn't part of base system on BSDs, so may not use /etc for configs.
Also, testing installation failed as non-root:
$ cmake -DBUILD_TESTS=1 -DCMAKE_INSTALL_PREFIX=/tmp/sdbus-cpp_prefix -DTESTS_INSTALL_PATH=/tmp/sdbus-cpp_prefix/tests
$ cmake --build .
$ cmake --install .
[...]
CMake Error at tests/cmake_install.cmake:105 (file):
file cannot create directory: /etc/dbus-1/system.d. Maybe need
administrative privileges.
* chore(tests): temporarily skip 1 test on FreeBSD to keep CI happy
* chore(ci): run tests in freebsd job
* feat: support serialization of array, span and unordered_map
* fix some spelling mistakes
* docs: update table of valid c++ types
---------
Co-authored-by: Marcel Hellwig <github@cookiesoft.de>
* Add methods to initiate custom session bus connection
The new function helper `createSessionBusConnectionWithAddress` allows to create connection to session bus with custom address.
Signed-off-by: Alexander Livenets <a.livenets@gmail.com>
* feat: add support for session bus connection at custom address
Co-authored-by: Stanislav Angelovic <stanislav.angelovic@siemens.com>
fix timeout handling
* Despite what is documented in sd_bus_get_timeout(3), the timeout
returned is actually an absolute time point of Linux's CLOCK_MONOTONIC
clock. Hence, we first have to subtract the current time from the
timeout in order to get a relative time that can be passed to poll.
* For async call timeouts to reliably work, we need a way to notify the
event loop of a connection that is currently blocked waiting in poll.
I.e. assume the event loop thread entered poll with a timeout set to
T1. Afterwards, the main thread starts an async call C with a timeout
T2 < T1. In order for C to be canceled after its timeout T1 has
elapsed, we have to be able to notify the event loop so that it can
update its poll data.
Co-authored-by: Urs Ritzmann <ursritzmann@protonmail.ch>
Co-authored-by: Lukasz Marcul <lukasz.marcul@onemeter.com>
This internally calls sd_bus_open(), which automatically selects the
system or session bus connection based on the presence and
content of a DBUS_STARTER_BUS_TYPE environment variable and
whether the calling process has root privileges.
This option is very helpful when creating services and clients that will use the system bus in production, but connect to a session
for testing.
Additional changes:
* Removed assertions null-checking make_unique() return values.
make_unique() calls new, and new is expected to throw or abort
on failure, making the assertions unhelpful.
* Corrected a typo in the ClosesAndUnrefsBusWhenDestructed
unit test for the system bus (tested the wrong function).
* Add missing nullptr check in Message::peekType().
* According to its specification, sd_bus_message_peek_type() sets a
given contents parameter to NULL if the next element in a message is
not a container. Since assigning a nullptr to a std::string has
undefined behaviour (typically resulting in an invalid memory access),
Message::peekType() must not assign contentsSig unconditionally.
* fix construct/destruct order of mutex/data in AsnycCalls
Destroying a mutex which might still be owned leads to undefined behaviour.
It wasn't the case here but using the right order is more resistant to future bugs.
* proxy AsnycCalls: don't leave map in unspecified state
* fix 133: use thread-safe container for proxy interfaces list
* proxy callback payload uses concrete signalData
* proxy: revert adding the wrapper class InterfaceContainer
It's no longer required and simplifies the locking logic.
* Proxy: avoid additional lambda wrapper around signal callbacks
As proposed in
https://github.com/Kistler-Group/sdbus-cpp/pull/177#issuecomment-834439707
option 3.
Still TODO: Avoid relying on std::map's non-invalidatable by adding just
std::unique_ptr<Proxy::InterfaceData::SignalData> to the container.
* proxy: add missing underscore prefix
* proxy: put InterfaceData::SignalData into a unique_ptr
This ways, we avoid relying on std::map's non-invalidatable references.
* proxy: code style: get raw pointer directly
* style: fix code style
Co-authored-by: Stanislav Angelovic <stanislav.angelovic@siemens.com>
* Add API to get message path
* Add API to get message destination
* Handle NULL message fields interface and member
Functions sd_bus_message_get_interface() and sd_bus_message_get_member()
can return null in case the message does not use those fields or does
not have them set.