Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package sdbus-cpp for openSUSE:Factory 
checked in at 2024-02-26 19:47:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/sdbus-cpp (Old)
 and      /work/SRC/openSUSE:Factory/.sdbus-cpp.new.1770 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "sdbus-cpp"

Mon Feb 26 19:47:09 2024 rev:8 rq:1151300 version:1.5.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/sdbus-cpp/sdbus-cpp.changes      2023-10-12 
11:58:02.963549121 +0200
+++ /work/SRC/openSUSE:Factory/.sdbus-cpp.new.1770/sdbus-cpp.changes    
2024-02-26 19:47:52.563299327 +0100
@@ -1,0 +2,12 @@
+* Mon Feb 26 11:58:42 UTC 2024 - Luca Boccassi <bl...@debian.org>
+
+- Update to new version 1.5.0:
+  - Improve handling of exceptions from callback handlers
+  - Add support for async registration of matches
+  - Correctly add libsystemd dependency to pkgconfi
+  - Fix request name signal handling issue
+  - Add INSTALL_TESTS CMake option
+  - Minor UnixFd cleanups
+  - Additional little fixes and updates in code, build system, CI, and 
documentation
+
+-------------------------------------------------------------------

Old:
----
  sdbus-cpp-1.4.0.tar.gz

New:
----
  sdbus-cpp-1.5.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ sdbus-cpp.spec ++++++
--- /var/tmp/diff_new_pack.vEuzfp/_old  2024-02-26 19:47:53.223323189 +0100
+++ /var/tmp/diff_new_pack.vEuzfp/_new  2024-02-26 19:47:53.223323189 +0100
@@ -1,8 +1,8 @@
 #
 # spec file for package sdbus-cpp
 #
-# Copyright (c) 2023 SUSE LLC
-# Copyright (c) 2021 Luca Boccassi <bl...@debian.org>
+# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2021-2024 Luca Boccassi <bl...@debian.org>
 # Copyright (c) 2020-2021 RedHat Inc.
 #
 # All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
 
 
 %global version_major 1
-%global version_minor 4
+%global version_minor 5
 %global version_micro 0
 
 Name:           sdbus-cpp

++++++ sdbus-cpp-1.4.0.tar.gz -> sdbus-cpp-1.5.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/.github/workflows/ci.yml 
new/sdbus-cpp-1.5.0/.github/workflows/ci.yml
--- old/sdbus-cpp-1.4.0/.github/workflows/ci.yml        2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/.github/workflows/ci.yml        2024-02-26 
08:29:35.000000000 +0100
@@ -48,19 +48,19 @@
       run: |
         mkdir build
         cd build
-        cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr 
-DCMAKE_CXX_FLAGS="-O0 -g -W -Wextra -Wall -Wnon-virtual-dtor -Werror" 
-DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON -DENABLE_PERF_TESTS=ON 
-DENABLE_STRESS_TESTS=ON -DBUILD_CODE_GEN=ON ..
+        cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX:PATH=/usr 
-DCMAKE_CXX_FLAGS="-O0 -g -W -Wextra -Wall -Wnon-virtual-dtor -Werror" 
-DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON -DINSTALL_TESTS=ON 
-DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON -DBUILD_CODE_GEN=ON ..
     - name: configure-release
       if: matrix.build == 'shared-libsystemd' && matrix.os == 'ubuntu-22.04'
       run: |
         mkdir build
         cd build
-        cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo 
-DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="-O3 -DNDEBUG -W -Wextra 
-Wall -Wnon-virtual-dtor -Werror" -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON 
-DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON -DBUILD_CODE_GEN=ON ..
+        cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo 
-DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_CXX_FLAGS="-O3 -DNDEBUG -W -Wextra 
-Wall -Wnon-virtual-dtor -Werror" -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON 
-DINSTALL_TESTS=ON -DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON 
-DBUILD_CODE_GEN=ON ..
     - name: configure-with-embedded-libsystemd
       if: matrix.build == 'embedded-static-libsystemd'
       run: |
         mkdir build
         cd build
-        cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr 
-DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON -DENABLE_PERF_TESTS=ON 
-DENABLE_STRESS_TESTS=ON -DBUILD_CODE_GEN=ON -DBUILD_LIBSYSTEMD=ON 
-DLIBSYSTEMD_VERSION=244 ..
+        cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr 
-DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_TESTS=ON -DINSTALL_TESTS=ON 
-DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON -DBUILD_CODE_GEN=ON 
-DBUILD_LIBSYSTEMD=ON -DLIBSYSTEMD_VERSION=244 ..
     - name: make
       run: |
         cd build
@@ -86,18 +86,18 @@
         retention-days: 10
   freebsd-build:
     name: build (freebsd, clang/libc++, basu)
-    runs-on: macos-12 # until https://github.com/actions/runner/issues/385
+    runs-on: ubuntu-22.04 # until https://github.com/actions/runner/issues/385
     steps:
     - uses: actions/checkout@v2
     - name: Test in FreeBSD VM
-      uses: vmactions/freebsd-vm@v0
+      uses: vmactions/freebsd-vm@v1
       with:
         copyback: false
         usesh: true
         prepare: |
           pkg install -y cmake ninja pkgconf basu expat googletest
         run: |
-          cmake -B _build -G Ninja -DBUILD_CODE_GEN=ON -DBUILD_TESTS=ON 
-DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON
+          cmake -B _build -G Ninja -DBUILD_CODE_GEN=ON -DBUILD_TESTS=ON 
-DINSTALL_TESTS=ON -DENABLE_PERF_TESTS=ON -DENABLE_STRESS_TESTS=ON
           cmake --build _build
           cmake --install _build
           pkg install -y dbus
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/CMakeLists.txt 
new/sdbus-cpp-1.5.0/CMakeLists.txt
--- old/sdbus-cpp-1.4.0/CMakeLists.txt  2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/CMakeLists.txt  2024-02-26 08:29:35.000000000 +0100
@@ -4,7 +4,7 @@
 
 cmake_minimum_required(VERSION 3.13)
 
-project(sdbus-c++ VERSION 1.4.0 LANGUAGES C CXX)
+project(sdbus-c++ VERSION 1.5.0 LANGUAGES C CXX)
 
 include(GNUInstallDirs) # Installation directories for `install` command and 
pkgconfig file
 
@@ -12,7 +12,8 @@
 # PERFORMING CHECKS & PREPARING THE DEPENDENCIES
 #-------------------------------
 
-set(LIBSYSTEMD "systemd")
+set(LIBSYSTEMD_IMPL "systemd")
+set(LIBSYSTEMD_LIB "libsystemd")
 
 option(BUILD_LIBSYSTEMD "Build libsystemd static library and incorporate it 
into libsdbus-c++" OFF)
 
@@ -23,13 +24,15 @@
         message(WARNING "libsystemd not found, checking for libelogind 
instead")
         pkg_check_modules(Systemd IMPORTED_TARGET GLOBAL libelogind>=236)
         if(TARGET PkgConfig::Systemd)
-            set(LIBSYSTEMD "elogind")
+            set(LIBSYSTEMD_IMPL "elogind")
+            set(LIBSYSTEMD_LIB "libelogind")
             string(REPLACE "." ";" VERSION_LIST ${Systemd_VERSION})
             list(GET VERSION_LIST 0 Systemd_VERSION)
-       else()
+        else()
             message(WARNING "libelogind not found, checking for basu instead")
             pkg_check_modules(Systemd IMPORTED_TARGET GLOBAL basu)
-            set(LIBSYSTEMD "basu")
+            set(LIBSYSTEMD_IMPL "basu")
+            set(LIBSYSTEMD_LIB "basu")
             # https://git.sr.ht/~emersion/basu/commit/d4d185d29a26
             set(Systemd_VERSION "240")
         endif()
@@ -125,8 +128,8 @@
 target_compile_definitions(sdbus-c++-objlib PRIVATE
     BUILD_LIB=1
     LIBSYSTEMD_VERSION=${LIBSYSTEMD_VERSION}
-    SDBUS_${LIBSYSTEMD}
-    SDBUS_HEADER=<${LIBSYSTEMD}/sd-bus.h>)
+    SDBUS_${LIBSYSTEMD_IMPL}
+    SDBUS_HEADER=<${LIBSYSTEMD_IMPL}/sd-bus.h>)
 target_include_directories(sdbus-c++-objlib PUBLIC 
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
                                                    
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>)
 if(BUILD_SHARED_LIBS)
@@ -169,7 +172,7 @@
 # TESTS
 #----------------------------------
 
-option(BUILD_TESTS "Build and install tests (default OFF)" OFF)
+option(BUILD_TESTS "Build tests (default OFF)" OFF)
 
 if(BUILD_TESTS)
     message(STATUS "Building with tests")
@@ -236,6 +239,7 @@
 else()
     set(PKGCONFIG_REQS "")
 endif()
+set(PKGCONFIG_DEPS ${LIBSYSTEMD_LIB})
 configure_file(pkgconfig/sdbus-c++.pc.in pkgconfig/sdbus-c++.pc @ONLY)
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/sdbus-c++.pc
         DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig COMPONENT dev)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/ChangeLog 
new/sdbus-cpp-1.5.0/ChangeLog
--- old/sdbus-cpp-1.4.0/ChangeLog       2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/ChangeLog       2024-02-26 08:29:35.000000000 +0100
@@ -239,3 +239,12 @@
 - Add support for direct, peer-to-peer connections
 - Add option to create IConnection directly from an underlying sd_bus instance
 - Some additional fixes
+
+v1.5.0
+- Improve handling of exceptions from callback handlers
+- Add support for async registration of matches
+- Correctly add libsystemd dependency to pkgconfi
+- Fix request name signal handling issue
+- Add INSTALL_TESTS CMake option
+- Minor UnixFd cleanups
+- Additional little fixes and updates in code, build system, CI, and 
documentation
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/README.md 
new/sdbus-cpp-1.5.0/README.md
--- old/sdbus-cpp-1.4.0/README.md       2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/README.md       2024-02-26 08:29:35.000000000 +0100
@@ -50,9 +50,13 @@
 
       Option for building sdbus-c++ stress tests. Default value: `OFF`.
 
+    * `INSTALL_TESTS` [boolean]
+
+      Option for installing tests that were built. Default value: `OFF`.
+
     * `TESTS_INSTALL_PATH` [string]
 
-      Path where the test binaries shall get installed. Default value: 
`/opt/test/bin`.
+      Path where the test binaries shall get installed. Default value: 
`${CMAKE_INSTALL_PREFIX}/tests/sdbus-c++` (previously: `/opt/test/bin`).
 
 * `BUILD_LIBSYSTEMD` [boolean]
 
@@ -82,7 +86,7 @@
 ------------
 
 * `C++17` - the library uses C++17 features.
-* `libsystemd` - systemd library containing sd-bus implementation. This 
library is part of systemd. Systemd at least v236 is needed. (In case you have 
a non-systemd environment, don't worry, see [Solving libsystemd 
dependency](docs/using-sdbus-c++.md#solving-libsystemd-dependency) for more 
information.)
+* `libsystemd`/`libelogind`/`basu` - libraries containing sd-bus 
implementation that sdbus-c++ is written around. In case of `libsystemd` and 
`libelogind`, version >= 236 is needed. (In case you have a non-systemd 
environment, don't worry, see [Solving libsystemd 
dependency](docs/using-sdbus-c++.md#solving-libsystemd-dependency) for more 
information.)
 * `googletest` - google unit testing framework, only necessary when building 
tests, will be downloaded and built automatically.
 * `pkgconfig` - required for sdbus-c++ to be able to find some dependency 
packages.
 * `expat` - necessary when building xml2cpp code generator (`BUILD_CODE_GEN` 
option is ON).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/docs/using-sdbus-c++.md 
new/sdbus-cpp-1.5.0/docs/using-sdbus-c++.md
--- old/sdbus-cpp-1.4.0/docs/using-sdbus-c++.md 2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/docs/using-sdbus-c++.md 2024-02-26 08:29:35.000000000 
+0100
@@ -75,13 +75,19 @@
 Solving libsystemd dependency
 -----------------------------
 
-sdbus-c++ depends on libsystemd, a C library that is part of 
[systemd](https://github.com/systemd/systemd) and that contains underlying 
sd-bus implementation.
+sdbus-c++ depends on sd-bus API, which is implemented in libsystemd, a C 
library that is part of [systemd](https://github.com/systemd/systemd).
 
 Minimum required libsystemd shared library version is 0.20.0 (which 
corresponds to minimum systemd version 236).
 
 If your target Linux distribution is already based on systemd ecosystem of 
version 236 and higher, then there is no additional effort, just make sure you 
have corresponding systemd header files available (provided by `libsystemd-dev` 
package on Debian/Ubuntu, for example), and you may go on building sdbus-c++ 
seamlessly.
 
-However, sdbus-c++ can perfectly be used in non-systemd environments as well. 
There are two ways to approach this:
+However, sdbus-c++ can perfectly be used in non-systemd environments as well. 
If `libsystemd` is not found in the system when configuring sdbus-c++, then
+
+1. sdbus-c++ will try to find `libelogind`, which is an extracted logind from 
original systemd containing sd-bus implementation. If not found, then
+
+2. sdbus-c++ will try to find `basu`, which is just sd-bus implementation 
extracted from systemd.
+
+On systems where neither of these is available, we can build sd-bus as a 
shared lib manually or we can (conveniently) instruct sdbus-c++ to build and 
integrate sd-bus into itself for us.
 
 ### Building and distributing libsystemd as a shared library yourself
 
@@ -101,7 +107,7 @@
 
 ### Building and distributing libsystemd as part of sdbus-c++
 
-sdbus-c++ provides `BUILD_LIBSYSTEMD` configuration option. When turned on, 
sdbus-c++ will automatically download and build libsystemd as a static library 
and make it an opaque part of sdbus-c++ shared library for you. This is the 
most convenient and effective approach to build, distribute and use sdbus-c++ 
as a self-contained, systemd-independent library in non-systemd environments. 
Just make sure your build machine has all dependencies needed by libsystemd 
build process. That includes, among others, `meson`, `ninja`, `git`, `gperf`, 
and -- primarily -- libraries and library headers for `libmount`, `libcap` and 
`librt` (part of glibc). Be sure to check out the systemd documentation for the 
 Also, when distributing, make sure these dependency libraries are installed on 
the production machine.
+sdbus-c++ provides `BUILD_LIBSYSTEMD` configuration option. When turned on, 
sdbus-c++ will automatically download and build libsystemd as a static library 
and make it an opaque part of sdbus-c++ shared library for you. This is the 
most convenient and effective approach to build, distribute and use sdbus-c++ 
as a self-contained, systemd-independent library in non-systemd environments. 
Just make sure your build machine has all dependencies needed by libsystemd 
build process. That includes, among others, `meson`, `ninja`, `git`, `gperf`, 
and -- primarily -- libraries and library headers for `libmount`, `libcap` and 
`librt` (part of glibc). Also, when distributing, make sure these dependency 
libraries are installed on the production machine.
 
 You may additionally set the `LIBSYSTEMD_VERSION` configuration flag to 
fine-tune the version of systemd to be taken in. (The default value is 242).
 
@@ -388,6 +394,27 @@
 
 Please note that we can create and destroy D-Bus object proxies dynamically, 
at any time during runtime, even when they share a common D-Bus connection and 
there is an active event loop upon the connection. So managing D-Bus object 
proxies' lifecycle (creating and destroying D-Bus object proxies) is completely 
thread-safe.
 
+### Opening bus connections in sdbus-c++
+
+There are several factory methods to create a bus connection object in 
sdbus-c++:
+
+* `createConnection()` - opens a connection to the system bus
+* `createConnection(const std::string& name)` - opens a connection with the 
given name to the system bus
+* `createDefaultBusConnection()` - opens a connection to the session bus when 
in a user context, and a connection to the system bus, otherwise
+* `createDefaultBusConnection(const std::string& name)` - opens a connection 
with the given name to the session bus when in a user context, and a connection 
with the given name to the system bus, otherwise
+* `createSystemBusConnection()` - opens a connection to the system bus
+* `createSystemBusConnection(const std::string& name)` - opens a connection 
with the given name to the system bus
+* `createSessionBusConnection()` - opens a connection to the session bus
+* `createSessionBusConnection(const std::string& name)` - opens a connection 
with the given name to the session bus
+* `createSessionBusConnectionWithAddress(const std::string& address)` - opens 
a connection to the session bus at a custom address
+* `createRemoteSystemBusConnection(const std::string& host)` - opens a 
connection to the system bus on a remote host using ssh
+* `createDirectBusConnection(const std::string& address)` - opens direct D-Bus 
connection at a custom address (see [Using direct (peer-to-peer) D-Bus 
connections](#using-direct-peer-to-peer-d-bus-connections))
+* `createDirectBusConnection(int fd)` - opens direct D-Bus connection at the 
given file descriptor (see [Using direct (peer-to-peer) D-Bus 
connections](#using-direct-peer-to-peer-d-bus-connections))
+* `createServerBus(int fd)` - opens direct D-Bus connection at the given file 
descriptor as a server (see [Using direct (peer-to-peer) D-Bus 
connections](#using-direct-peer-to-peer-d-bus-connections))
+* `createBusConnection(sd_bus *bus)` - creates a connection directly from the 
underlying sd_bus connection instance (which has been created and set up 
upfront directly through sd-bus API).
+
+For more information, peek into 
[`IConnection.h`](/include/sdbus-c++/IConnection.h) where these functions are 
declared and documented.
+
 ### Working with D-Bus connections in sdbus-c++
 
 The design of D-Bus connections in sdbus-c++ allows for certain flexibility 
and enables users to choose simplicity over scalability or scalability (at a 
finer granularity of user's choice) at the cost of slightly decreased 
simplicity.
@@ -565,6 +592,7 @@
 >         assert(e->getMessage() == "Failed to deserialize a int32 value");
 >     }
 > ```
+> Signature mismatch in signal handlers is probably the most common reason why 
signals are not received in the client, while we can see them on the bus with 
`dbus-monitor`. Use `const sdbus::Error*`-based callback variant and inspect 
the error to check if that's the cause of such problems.
 
 > **_Tip_:** When registering a D-Bus object, we can additionally provide 
 > names of input and output parameters of its methods and names of parameters 
 > of its signals. When the object is introspected, these names are listed in 
 > the resulting introspection XML, which improves the description of object's 
 > interfaces:
 > ```c++
@@ -1512,10 +1540,10 @@
 
 We need two things to do that:
 
-* implement `sdbus::Message` insertion and extraction operators, so sdbus-c++ 
knows how to serialize/deserialize our custom type,
+* implement `sdbus::Message` insertion (serialization) and extraction 
(deserialization) operators, so sdbus-c++ knows how to serialize/deserialize 
our custom type,
 * specialize `sdbus::signature_of` template for our custom type, so sdbus-c++ 
knows the mapping to D-Bus type and other necessary information about our type.
 
-Say, we would like to represent D-Bus arrays as `std::list`s in our 
application. Since sdbus-c++ comes with pre-defined support for `std::vector`s, 
`std::array`s and `std::span`s as D-Bus array representations, we have to 
provide an extension:
+Say, we would like to represent D-Bus arrays as `std::list`s in our 
application. Since sdbus-c++ comes with pre-defined support for `std::vector`s, 
`std::array`s and `std::span`s as D-Bus array representations, we have to 
provide an extension. To implement message serialization and deserialization 
functions for `std::list`, we can simply copy the sdbus-c++ implementation of 
these functions for `std::vector`, and simply adjust for `std::list`. Then we 
provide `signature_of` specialization, again written on terms of one 
specialized for `std::vector`:
 
 ```c++
 #include <list>
@@ -1568,12 +1596,11 @@
 struct sdbus::signature_of<std::list<_Element, _Allocator>>
         : sdbus::signature_of<std::vector<_Element, _Allocator>>
 {};
-};
 ```
 
 Then we can simply use `std::list`s, serialize/deserialize them in a D-Bus 
message, in D-Bus method calls or return values... and they will be simply 
transmitted as D-Bus arrays.
 
-As another example, say we have our custom type `my::Struct` which we'd like 
to use as a D-Bus structure representation (sdbus-c++ provides `sdbus::Struct` 
type for that, but we don't want to use it because using our custom type 
directly is more convenient). Again, we have to provide type traits and message 
serialization/deserialization functions for our custom type. We build our 
functions and specializations on top of `sdbus::Struct`, so we don't have to 
copy and write a lot of boiler-plate:
+As another example, say we have our custom type `my::Struct` which we'd like 
to use as a D-Bus structure representation (sdbus-c++ provides `sdbus::Struct` 
type for that, but we don't want to use it because using our custom type 
directly is more convenient). Again, we have to provide type traits and message 
serialization/deserialization functions for our custom type. We build our 
functions and specializations on top of `sdbus::Struct`, so we don't have to 
copy and write a lot of boiler-plate. Serialization/deserialization functions 
can be placed in the same namespace as our custom type, and will be found 
thanks to the ADR lookup. The `signature_of` specialization must always be in 
either `sdbus` namespace or in a global namespace:
 
 ```c++
 namespace my {
@@ -1596,7 +1623,7 @@
         sdbus::Struct s{std::forward_as_tuple(items.i, items.s, items.l)};
         return msg >> s;
     }
-}
+} // namespace my
 
 template <>
 struct sdbus::signature_of<my::Struct>
@@ -1611,7 +1638,7 @@
 Support for match rules
 -----------------------
 
-`IConnection` class provides `addMatch` method that you can use to install 
match rules. An associated callback handler will be called upon an incoming 
message matching given match rule. There is support for both client-owned and 
floating (library-owned) match rules. Consult `IConnection` header or sdbus-c++ 
doxygen documentation for more information.
+`IConnection` class provides `addMatch` and `addMatchAsync` family of methods 
that you can use to install match rules on that bus connection. An associated 
callback handler will be called when an incoming D-Bus message matches the 
given match rule. Clients can decide whether they own and control the match 
rule lifetime, or whether the match rule lifetime is bound the connection 
object lifetime (so-called floating match rule). Consult `IConnection` header 
or sdbus-c++ doxygen documentation for more information.
 
 Using direct (peer-to-peer) D-Bus connections
 ---------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sdbus-cpp-1.4.0/include/sdbus-c++/ConvenienceApiClasses.inl 
new/sdbus-cpp-1.5.0/include/sdbus-c++/ConvenienceApiClasses.inl
--- old/sdbus-cpp-1.4.0/include/sdbus-c++/ConvenienceApiClasses.inl     
2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/include/sdbus-c++/ConvenienceApiClasses.inl     
2024-02-26 08:29:35.000000000 +0100
@@ -595,9 +595,8 @@
                 }
                 catch (const Error& e)
                 {
-                    // Catch message unpack exceptions and pass them to the 
callback
-                    // in the expected manner to avoid propagating them up the 
call
-                    // stack to the event loop.
+                    // Pass message deserialization exceptions to the client 
via callback error parameter,
+                    // instead of propagating them up the message loop call 
stack.
                     sdbus::apply(callback, &e, args);
                     return;
                 }
@@ -676,8 +675,10 @@
                 }
                 catch (const sdbus::Error& e)
                 {
-                    // Invoke callback with error argument and input arguments 
from the tuple.
+                    // Pass message deserialization exceptions to the client 
via callback error parameter,
+                    // instead of propagating them up the message loop call 
stack.
                     sdbus::apply(callback, &e, signalArgs);
+                    return;
                 }
 
                 // Invoke callback with no error and input arguments from the 
tuple.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/include/sdbus-c++/Error.h 
new/sdbus-cpp-1.5.0/include/sdbus-c++/Error.h
--- old/sdbus-cpp-1.4.0/include/sdbus-c++/Error.h       2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/include/sdbus-c++/Error.h       2024-02-26 
08:29:35.000000000 +0100
@@ -76,6 +76,8 @@
     };
 
     sdbus::Error createError(int errNo, const std::string& customMsg);
+
+    inline const char* SDBUSCPP_ERROR_NAME = "org.sdbuscpp.Error";
 }
 
 #define SDBUS_THROW_ERROR(_MSG, _ERRNO)                         \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/include/sdbus-c++/IConnection.h 
new/sdbus-cpp-1.5.0/include/sdbus-c++/IConnection.h
--- old/sdbus-cpp-1.4.0/include/sdbus-c++/IConnection.h 2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/include/sdbus-c++/IConnection.h 2024-02-26 
08:29:35.000000000 +0100
@@ -268,10 +268,10 @@
         virtual void addObjectManager(const std::string& objectPath, 
floating_slot_t) = 0;
 
         /*!
-         * @brief Adds a match rule for incoming message dispatching
+         * @brief Installs a match rule for messages received on this bus 
connection
          *
          * @param[in] match Match expression to filter incoming D-Bus message
-         * @param[in] callback Callback handler to be called upon incoming 
D-Bus message matching the rule
+         * @param[in] callback Callback handler to be called upon processing 
an inbound D-Bus message matching the rule
          * @return RAII-style slot handle representing the ownership of the 
subscription
          *
          * The method installs a match rule for messages received on the 
specified bus connection.
@@ -291,10 +291,10 @@
         [[nodiscard]] virtual Slot addMatch(const std::string& match, 
message_handler callback) = 0;
 
         /*!
-         * @brief Adds a floating match rule for incoming message dispatching
+         * @brief Installs a floating match rule for messages received on this 
bus connection
          *
          * @param[in] match Match expression to filter incoming D-Bus message
-         * @param[in] callback Callback handler to be called upon incoming 
D-Bus message matching the rule
+         * @param[in] callback Callback handler to be called upon processing 
an inbound D-Bus message matching the rule
          *
          * The method installs a floating match rule for messages received on 
the specified bus connection.
          * Floating means that the bus connection object owns the match rule, 
i.e. lifetime of the match rule
@@ -308,6 +308,45 @@
         virtual void addMatch(const std::string& match, message_handler 
callback, floating_slot_t) = 0;
 
         /*!
+         * @brief Asynchronously installs a match rule for messages received 
on this bus connection
+         *
+         * @param[in] match Match expression to filter incoming D-Bus message
+         * @param[in] callback Callback handler to be called upon processing 
an inbound D-Bus message matching the rule
+         * @param[in] installCallback Callback handler to be called upon 
processing an inbound D-Bus message matching the rule
+         * @return RAII-style slot handle representing the ownership of the 
subscription
+         *
+         * This method operates the same as `addMatch()` above, just that it 
installs the match rule asynchronously,
+         * in a non-blocking fashion. A request is sent to the broker, but the 
call does not wait for a response.
+         * The `installCallback' callable is called when the response is later 
received, with the response message
+         * from the broker as parameter. If it's an empty function object, a 
default implementation is used that
+         * terminates the bus connection should installing the match fail.
+         *
+         * Refer to the @c addMatch(const std::string& match, message_handler 
callback) documentation, and consult
+         * `man sd_bus_add_match`, for more information.
+         *
+         * @throws sdbus::Error in case of failure
+         */
+        [[nodiscard]] virtual Slot addMatchAsync(const std::string& match, 
message_handler callback, message_handler installCallback) = 0;
+
+        /*!
+         * @brief Asynchronously installs a floating match rule for messages 
received on this bus connection
+         *
+         * @param[in] match Match expression to filter incoming D-Bus message
+         * @param[in] callback Callback handler to be called upon processing 
an inbound D-Bus message matching the rule
+         * @param[in] installCallback Callback handler to be called upon 
processing an inbound D-Bus message matching the rule
+         *
+         * The method installs a floating match rule for messages received on 
the specified bus connection.
+         * Floating means that the bus connection object owns the match rule, 
i.e. lifetime of the match rule
+         * is bound to the lifetime of the bus connection.
+         *
+         * Refer to the @c addMatch(const std::string& match, message_handler 
callback, message_handler installCallback)
+         * documentation for more information.
+         *
+         * @throws sdbus::Error in case of failure
+         */
+        virtual void addMatchAsync(const std::string& match, message_handler 
callback, message_handler installCallback, floating_slot_t) = 0;
+
+        /*!
          * @copydoc IConnection::enterEventLoop()
          *
          * @deprecated This function has been replaced by enterEventLoop()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/include/sdbus-c++/Message.h 
new/sdbus-cpp-1.5.0/include/sdbus-c++/Message.h
--- old/sdbus-cpp-1.4.0/include/sdbus-c++/Message.h     2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/include/sdbus-c++/Message.h     2024-02-26 
08:29:35.000000000 +0100
@@ -42,6 +42,7 @@
 #include <cassert>
 #include <functional>
 #include <sys/types.h>
+#include <algorithm>
 
 // Forward declarations
 namespace sdbus {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/include/sdbus-c++/Types.h 
new/sdbus-cpp-1.5.0/include/sdbus-c++/Types.h
--- old/sdbus-cpp-1.4.0/include/sdbus-c++/Types.h       2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/include/sdbus-c++/Types.h       2024-02-26 
08:29:35.000000000 +0100
@@ -34,7 +34,7 @@
 #include <typeinfo>
 #include <memory>
 #include <tuple>
-#include <unistd.h>
+#include <utility>
 
 namespace sdbus {
 
@@ -56,7 +56,7 @@
         Variant();
 
         template <typename _ValueType>
-        /*explicit*/ Variant(const _ValueType& value) // TODO: Mark explicit 
in new major version so we don't break client code within v1
+        Variant(const _ValueType& value)
             : Variant()
         {
             msg_.openVariant(signature_of<_ValueType>::str());
@@ -209,7 +209,7 @@
         UnixFd() = default;
 
         explicit UnixFd(int fd)
-            : fd_(::dup(fd))
+            : fd_(checkedDup(fd))
         {
         }
 
@@ -225,8 +225,12 @@
 
         UnixFd& operator=(const UnixFd& other)
         {
+            if (this == &other)
+            {
+                return *this;
+            }
             close();
-            fd_ = ::dup(other.fd_);
+            fd_ = checkedDup(other.fd_);
             return *this;
         }
 
@@ -237,9 +241,12 @@
 
         UnixFd& operator=(UnixFd&& other)
         {
+            if (this == &other)
+            {
+                return *this;
+            }
             close();
-            fd_ = other.fd_;
-            other.fd_ = -1;
+            fd_ = std::exchange(other.fd_, -1);
             return *this;
         }
 
@@ -265,9 +272,7 @@
 
         int release()
         {
-            auto fd = fd_;
-            fd_ = -1;
-            return fd;
+            return std::exchange(fd_, -1);
         }
 
         bool isValid() const
@@ -276,11 +281,12 @@
         }
 
     private:
-        void close()
-        {
-            if (fd_ >= 0)
-                ::close(fd_);
-        }
+        /// Closes file descriptor, but does not set it to -1.
+        void close();
+
+        /// Returns negative argument unchanged.
+        /// Otherwise, call ::dup and throw on failure.
+        static int checkedDup(int fd);
 
         int fd_ = -1;
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/pkgconfig/sdbus-c++.pc.in 
new/sdbus-cpp-1.5.0/pkgconfig/sdbus-c++.pc.in
--- old/sdbus-cpp-1.4.0/pkgconfig/sdbus-c++.pc.in       2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/pkgconfig/sdbus-c++.pc.in       2024-02-26 
08:29:35.000000000 +0100
@@ -5,7 +5,7 @@
 
 Name: @PROJECT_NAME@
 Description: C++ library on top of sd-bus, a systemd D-Bus library
-Requires@PKGCONFIG_REQS@: @LIBSYSTEMD@
+Requires@PKGCONFIG_REQS@: @PKGCONFIG_DEPS@
 Version: @SDBUSCPP_VERSION@
 Libs: -L${libdir} -l@PROJECT_NAME@
 Cflags: -I${includedir}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Connection.cpp 
new/sdbus-cpp-1.5.0/src/Connection.cpp
--- old/sdbus-cpp-1.4.0/src/Connection.cpp      2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/src/Connection.cpp      2024-02-26 08:29:35.000000000 
+0100
@@ -108,12 +108,20 @@
 
     auto r = iface_->sd_bus_request_name(bus_.get(), name.c_str(), 0);
     SDBUS_THROW_ERROR_IF(r < 0, "Failed to request bus name", -r);
+
+    // In some cases we need to explicitly notify the event loop
+    // to process messages that may have arrived while executing the call.
+    notifyEventLoop(eventFd_.fd);
 }
 
 void Connection::releaseName(const std::string& name)
 {
     auto r = iface_->sd_bus_release_name(bus_.get(), name.c_str());
     SDBUS_THROW_ERROR_IF(r < 0, "Failed to release bus name", -r);
+
+    // In some cases we need to explicitly notify the event loop
+    // to process messages that may have arrived while executing the call.
+    notifyEventLoop(eventFd_.fd);
 }
 
 std::string Connection::getUniqueName() const
@@ -217,17 +225,11 @@
 
 Slot Connection::addMatch(const std::string& match, message_handler callback)
 {
-    auto matchInfo = 
std::make_unique<MatchInfo>(MatchInfo{std::move(callback), *this, {}});
+    SDBUS_THROW_ERROR_IF(!callback, "Invalid match callback handler provided", 
EINVAL);
 
-    auto messageHandler = [](sd_bus_message *sdbusMessage, void *userData, 
sd_bus_error */*retError*/) -> int
-    {
-        auto* matchInfo = static_cast<MatchInfo*>(userData);
-        auto message = Message::Factory::create<PlainMessage>(sdbusMessage, 
&matchInfo->connection.getSdBusInterface());
-        matchInfo->callback(message);
-        return 0;
-    };
+    auto matchInfo = 
std::make_unique<MatchInfo>(MatchInfo{std::move(callback), {}, *this, {}});
 
-    auto r = iface_->sd_bus_add_match(bus_.get(), &matchInfo->slot, 
match.c_str(), std::move(messageHandler), matchInfo.get());
+    auto r = iface_->sd_bus_add_match(bus_.get(), &matchInfo->slot, 
match.c_str(), &Connection::sdbus_match_callback, matchInfo.get());
     SDBUS_THROW_ERROR_IF(r < 0, "Failed to add match", -r);
 
     return {matchInfo.release(), [this](void *ptr)
@@ -243,6 +245,34 @@
     floatingMatchRules_.push_back(addMatch(match, std::move(callback)));
 }
 
+Slot Connection::addMatchAsync(const std::string& match, message_handler 
callback, message_handler installCallback)
+{
+    SDBUS_THROW_ERROR_IF(!callback, "Invalid match callback handler provided", 
EINVAL);
+
+    sd_bus_message_handler_t sdbusInstallCallback = installCallback ? 
&Connection::sdbus_match_install_callback : nullptr;
+    auto matchInfo = 
std::make_unique<MatchInfo>(MatchInfo{std::move(callback), 
std::move(installCallback), *this, {}});
+
+    auto r = iface_->sd_bus_add_match_async( bus_.get()
+                                           , &matchInfo->slot
+                                           , match.c_str()
+                                           , &Connection::sdbus_match_callback
+                                           , sdbusInstallCallback
+                                           , matchInfo.get());
+    SDBUS_THROW_ERROR_IF(r < 0, "Failed to add match", -r);
+
+    return {matchInfo.release(), [this](void *ptr)
+    {
+        auto* matchInfo = static_cast<MatchInfo*>(ptr);
+        iface_->sd_bus_slot_unref(matchInfo->slot);
+        std::default_delete<MatchInfo>{}(matchInfo);
+    }};
+}
+
+void Connection::addMatchAsync(const std::string& match, message_handler 
callback, message_handler installCallback, floating_slot_t)
+{
+    floatingMatchRules_.push_back(addMatchAsync(match, std::move(callback), 
std::move(installCallback)));
+}
+
 Slot Connection::addObjectVTable( const std::string& objectPath
                                 , const std::string& interfaceName
                                 , const sd_bus_vtable* vtable
@@ -565,6 +595,22 @@
     return strv;
 }
 
+int Connection::sdbus_match_callback(sd_bus_message *sdbusMessage, void 
*userData, sd_bus_error *retError)
+{
+    auto* matchInfo = static_cast<MatchInfo*>(userData);
+    auto message = Message::Factory::create<PlainMessage>(sdbusMessage, 
&matchInfo->connection.getSdBusInterface());
+    auto ok = invokeHandlerAndCatchErrors([&](){ matchInfo->callback(message); 
}, retError);
+    return ok ? 0 : -1;
+}
+
+int Connection::sdbus_match_install_callback(sd_bus_message *sdbusMessage, 
void *userData, sd_bus_error *retError)
+{
+    auto* matchInfo = static_cast<MatchInfo*>(userData);
+    auto message = Message::Factory::create<PlainMessage>(sdbusMessage, 
&matchInfo->connection.getSdBusInterface());
+    auto ok = invokeHandlerAndCatchErrors([&](){ 
matchInfo->installCallback(message); }, retError);
+    return ok ? 0 : -1;
+}
+
 Connection::EventFd::EventFd()
 {
     fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Connection.h 
new/sdbus-cpp-1.5.0/src/Connection.h
--- old/sdbus-cpp-1.4.0/src/Connection.h        2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/src/Connection.h        2024-02-26 08:29:35.000000000 
+0100
@@ -96,6 +96,8 @@
 
         [[nodiscard]] Slot addMatch(const std::string& match, message_handler 
callback) override;
         void addMatch(const std::string& match, message_handler callback, 
floating_slot_t) override;
+        [[nodiscard]] Slot addMatchAsync(const std::string& match, 
message_handler callback, message_handler installCallback) override;
+        void addMatchAsync(const std::string& match, message_handler callback, 
message_handler installCallback, floating_slot_t) override;
 
         const ISdBus& getSdBusInterface() const override;
         ISdBus& getSdBusInterface() override;
@@ -151,10 +153,13 @@
         void clearEventLoopNotification(int fd) const;
         void notifyEventLoopNewTimeout() const override;
 
-    private:
         void joinWithEventLoop();
         static std::vector</*const */char*> to_strv(const 
std::vector<std::string>& strings);
 
+        static int sdbus_match_callback(sd_bus_message *sdbusMessage, void 
*userData, sd_bus_error *retError);
+        static int sdbus_match_install_callback(sd_bus_message *sdbusMessage, 
void *userData, sd_bus_error *retError);
+
+    private:
         struct EventFd
         {
             EventFd();
@@ -165,6 +170,7 @@
         struct MatchInfo
         {
             message_handler callback;
+            message_handler installCallback;
             Connection& connection;
             sd_bus_slot *slot;
         };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/ISdBus.h 
new/sdbus-cpp-1.5.0/src/ISdBus.h
--- old/sdbus-cpp-1.4.0/src/ISdBus.h    2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/ISdBus.h    2024-02-26 08:29:35.000000000 +0100
@@ -80,6 +80,7 @@
         virtual int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, 
const char *path, const char *interface, const sd_bus_vtable *vtable, void 
*userdata) = 0;
         virtual int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, 
const char *path) = 0;
         virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const 
char *match, sd_bus_message_handler_t callback, void *userdata) = 0;
+        virtual int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, 
const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t 
install_callback, void *userdata) = 0;
         virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) = 0;
 
         virtual int sd_bus_new(sd_bus **ret) = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Object.cpp 
new/sdbus-cpp-1.5.0/src/Object.cpp
--- old/sdbus-cpp-1.4.0/src/Object.cpp  2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/Object.cpp  2024-02-26 08:29:35.000000000 +0100
@@ -347,16 +347,9 @@
     auto& callback = interfaceData->methods[message.getMemberName()].callback;
     assert(callback);
 
-    try
-    {
-        callback(message);
-    }
-    catch (const Error& e)
-    {
-        sd_bus_error_set(retError, e.getName().c_str(), 
e.getMessage().c_str());
-    }
+    auto ok = invokeHandlerAndCatchErrors([&](){ callback(message); }, 
retError);
 
-    return 1;
+    return ok ? 1 : -1;
 }
 
 int Object::sdbus_property_get_callback( sd_bus */*bus*/
@@ -381,16 +374,9 @@
 
     auto reply = Message::Factory::create<PropertyGetReply>(sdbusReply, 
&object.connection_.getSdBusInterface());
 
-    try
-    {
-        callback(reply);
-    }
-    catch (const Error& e)
-    {
-        sd_bus_error_set(retError, e.getName().c_str(), 
e.getMessage().c_str());
-    }
+    auto ok = invokeHandlerAndCatchErrors([&](){ callback(reply); }, retError);
 
-    return 1;
+    return ok ? 1 : -1;
 }
 
 int Object::sdbus_property_set_callback( sd_bus */*bus*/
@@ -416,16 +402,9 @@
         object.m_CurrentlyProcessedMessage.store(nullptr, 
std::memory_order_relaxed);
     };
 
-    try
-    {
-        callback(value);
-    }
-    catch (const Error& e)
-    {
-        sd_bus_error_set(retError, e.getName().c_str(), 
e.getMessage().c_str());
-    }
+    auto ok = invokeHandlerAndCatchErrors([&](){ callback(value); }, retError);
 
-    return 1;
+    return ok ? 1 : -1;
 }
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Proxy.cpp 
new/sdbus-cpp-1.5.0/src/Proxy.cpp
--- old/sdbus-cpp-1.4.0/src/Proxy.cpp   2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/Proxy.cpp   2024-02-26 08:29:35.000000000 +0100
@@ -143,7 +143,7 @@
     async_reply_handler asyncReplyCallback = [promise = 
std::move(promise)](MethodReply& reply, const Error* error) noexcept
     {
         if (error == nullptr)
-            promise->set_value(reply); // TODO: std::move? Can't move now 
because currently processed message. TODO: Refactor
+            promise->set_value(reply);
         else
             promise->set_exception(std::make_exception_ptr(*error));
     };
@@ -269,7 +269,7 @@
     return m_CurrentlyProcessedMessage.load(std::memory_order_relaxed);
 }
 
-int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void 
*userData, sd_bus_error */*retError*/)
+int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void 
*userData, sd_bus_error *retError)
 {
     auto* asyncCallData = static_cast<AsyncCalls::CallData*>(userData);
     assert(asyncCallData != nullptr);
@@ -295,7 +295,7 @@
         proxy.m_CurrentlyProcessedMessage.store(nullptr, 
std::memory_order_relaxed);
     };
 
-    try
+    auto ok = invokeHandlerAndCatchErrors([&]
     {
         const auto* error = sd_bus_message_get_error(sdbusMessage);
         if (error == nullptr)
@@ -307,16 +307,12 @@
             Error exception(error->name, error->message);
             asyncCallData->callback(message, &exception);
         }
-    }
-    catch (const Error&)
-    {
-        // Intentionally left blank -- sdbus-c++ exceptions shall not bubble 
up to the underlying C sd-bus library
-    }
+    }, retError);
 
-    return 0;
+    return ok ? 0 : -1;
 }
 
-int Proxy::sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, 
sd_bus_error */*retError*/)
+int Proxy::sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, 
sd_bus_error *retError)
 {
     auto* signalData = static_cast<InterfaceData::SignalData*>(userData);
     assert(signalData != nullptr);
@@ -330,16 +326,9 @@
         signalData->proxy.m_CurrentlyProcessedMessage.store(nullptr, 
std::memory_order_relaxed);
     };
 
-    try
-    {
-        signalData->callback(message);
-    }
-    catch (const Error&)
-    {
-        // Intentionally left blank -- sdbus-c++ exceptions shall not bubble 
up to the underlying C sd-bus library
-    }
+    auto ok = invokeHandlerAndCatchErrors([&](){ 
signalData->callback(message); }, retError);
 
-    return 0;
+    return ok ? 0 : -1;
 }
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/ScopeGuard.h 
new/sdbus-cpp-1.5.0/src/ScopeGuard.h
--- old/sdbus-cpp-1.4.0/src/ScopeGuard.h        2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/src/ScopeGuard.h        2024-02-26 08:29:35.000000000 
+0100
@@ -55,62 +55,104 @@
 //     return; // exiting scope normally
 // }
 
-#define SCOPE_EXIT                                               \
-    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE)                    \
-        = ::sdbus::internal::detail::ScopeGuardOnExit() + [&]()  \
+#define SCOPE_EXIT                                                \
+    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE)                     \
+        = ::sdbus::internal::ScopeGuardOnExitTag{} + [&]()        \
     /**/
-
-#define SCOPE_EXIT_NAMED(NAME)                                   \
-    auto NAME                                                    \
-        = ::sdbus::internal::detail::ScopeGuardOnExit() + [&]()  \
+#define SCOPE_EXIT_NAMED(NAME)                                    \
+    auto NAME                                                     \
+        = ::sdbus::internal::ScopeGuardOnExitTag{} + [&]()        \
+    /**/
+#define SCOPE_EXIT_SUCCESS                                        \
+    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE)                     \
+        = ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \
+    /**/
+#define SCOPE_EXIT_SUCCESS_NAMED(NAME)                            \
+    auto NAME                                                     \
+        = ::sdbus::internal::ScopeGuardOnExitSuccessTag{} + [&]() \
+    /**/
+#define SCOPE_EXIT_FAILURE                                        \
+    auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE)                     \
+        = ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \
+    /**/
+#define SCOPE_EXIT_FAILURE_NAMED(NAME)                            \
+    auto NAME                                                     \
+        = ::sdbus::internal::ScopeGuardOnExitFailureTag{} + [&]() \
     /**/
 
 namespace sdbus::internal {
 
-    template <class _Fun>
-    class ScopeGuard
+    struct ScopeGuardOnExitTag
     {
-        _Fun fnc_;
-        bool active_;
-
-    public:
-        ScopeGuard(_Fun f)
-            : fnc_(std::move(f))
-            , active_(true)
+        static bool holds(int /*originalExceptions*/)
         {
+            return true; // Always holds
         }
-        ~ScopeGuard()
+    };
+    struct ScopeGuardOnExitSuccessTag
+    {
+        static bool holds(int originalExceptions)
         {
-            if (active_)
-                fnc_();
+            return originalExceptions == std::uncaught_exceptions(); // Only 
holds when no exception occurred within the scope
         }
-        void dismiss()
+    };
+    struct ScopeGuardOnExitFailureTag
+    {
+        static bool holds(int originalExceptions)
         {
-            active_ = false;
+            return originalExceptions != std::uncaught_exceptions(); // Only 
holds when an exception occurred within the scope
         }
+    };
+
+    template <class _Fun, typename _Tag>
+    class ScopeGuard
+    {
+    public:
+        ScopeGuard(_Fun f) : fnc_(std::move(f))
+        {
+        }
+
         ScopeGuard() = delete;
         ScopeGuard(const ScopeGuard&) = delete;
         ScopeGuard& operator=(const ScopeGuard&) = delete;
-        ScopeGuard(ScopeGuard&& rhs)
-            : fnc_(std::move(rhs.fnc_))
-            , active_(rhs.active_)
+        ScopeGuard(ScopeGuard&& rhs) : fnc_(std::move(rhs.fnc_)), 
active_(rhs.active_), exceptions_(rhs.exceptions_)
         {
             rhs.dismiss();
         }
-    };
 
-    namespace detail
-    {
-        enum class ScopeGuardOnExit
+        void dismiss()
         {
-        };
+            active_ = false;
+        }
 
-        // Helper function to auto-deduce type of the callable entity
-        template <typename _Fun>
-        ScopeGuard<_Fun> operator+(ScopeGuardOnExit, _Fun&& fnc)
+        ~ScopeGuard()
         {
-            return ScopeGuard<_Fun>(std::forward<_Fun>(fnc));
+            if (active_ && _Tag::holds(exceptions_))
+                fnc_();
         }
+
+    private:
+        _Fun fnc_;
+        int exceptions_{std::uncaught_exceptions()};
+        bool active_{true};
+    };
+
+    template <typename _Fun>
+    ScopeGuard<_Fun, ScopeGuardOnExitTag> operator+(ScopeGuardOnExitTag, 
_Fun&& fnc)
+    {
+        return ScopeGuard<_Fun, ScopeGuardOnExitTag>(std::forward<_Fun>(fnc));
+    }
+
+    template <typename _Fun>
+    ScopeGuard<_Fun, ScopeGuardOnExitSuccessTag> 
operator+(ScopeGuardOnExitSuccessTag, _Fun&& fnc)
+    {
+        return ScopeGuard<_Fun, 
ScopeGuardOnExitSuccessTag>(std::forward<_Fun>(fnc));
+    }
+
+    template <typename _Fun>
+    ScopeGuard<_Fun, ScopeGuardOnExitFailureTag> 
operator+(ScopeGuardOnExitFailureTag, _Fun&& fnc)
+    {
+        return ScopeGuard<_Fun, 
ScopeGuardOnExitFailureTag>(std::forward<_Fun>(fnc));
     }
 
 }
@@ -119,13 +161,9 @@
 #define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
 
 #ifdef __COUNTER__
-#define ANONYMOUS_VARIABLE(str)                 \
-    CONCATENATE(str, __COUNTER__)               \
-    /**/
+#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
 #else
-#define ANONYMOUS_VARIABLE(str)                 \
-    CONCATENATE(str, __LINE__)                  \
-    /**/
+#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __LINE__)
 #endif
 
 #endif /* SDBUS_CPP_INTERNAL_SCOPEGUARD_H_ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/SdBus.cpp 
new/sdbus-cpp-1.5.0/src/SdBus.cpp
--- old/sdbus-cpp-1.4.0/src/SdBus.cpp   2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/SdBus.cpp   2024-02-26 08:29:35.000000000 +0100
@@ -345,6 +345,13 @@
     return ::sd_bus_add_match(bus, slot, match, callback, userdata);
 }
 
+int SdBus::sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char 
*match, sd_bus_message_handler_t callback, sd_bus_message_handler_t 
install_callback, void *userdata)
+{
+    std::lock_guard lock(sdbusMutex_);
+
+    return ::sd_bus_add_match_async(bus, slot, match, callback, 
install_callback, userdata);
+}
+
 sd_bus_slot* SdBus::sd_bus_slot_unref(sd_bus_slot *slot)
 {
     std::lock_guard lock(sdbusMutex_);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/SdBus.h 
new/sdbus-cpp-1.5.0/src/SdBus.h
--- old/sdbus-cpp-1.4.0/src/SdBus.h     2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/SdBus.h     2024-02-26 08:29:35.000000000 +0100
@@ -72,6 +72,7 @@
     virtual int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, 
const char *path, const char *interface, const sd_bus_vtable *vtable, void 
*userdata) override;
     virtual int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, 
const char *path) override;
     virtual int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char 
*match, sd_bus_message_handler_t callback, void *userdata) override;
+    virtual int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const 
char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t 
install_callback, void *userdata) override;
     virtual sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) override;
 
     virtual int sd_bus_new(sd_bus **ret) override;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Types.cpp 
new/sdbus-cpp-1.5.0/src/Types.cpp
--- old/sdbus-cpp-1.4.0/src/Types.cpp   2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/Types.cpp   2024-02-26 08:29:35.000000000 +0100
@@ -29,6 +29,9 @@
 #include "MessageUtils.h"
 #include SDBUS_HEADER
 #include <cassert>
+#include <cerrno>
+#include <system_error>
+#include <unistd.h>
 
 namespace sdbus {
 
@@ -64,4 +67,27 @@
     return msg_.isEmpty();
 }
 
+void UnixFd::close()
+{
+    if (fd_ >= 0)
+    {
+        ::close(fd_);
+    }
+}
+
+int UnixFd::checkedDup(int fd)
+{
+    if (fd < 0)
+    {
+        return fd;
+    }
+
+    int ret = ::dup(fd);
+    if (ret < 0)
+    {
+        throw std::system_error(errno, std::generic_category(), "dup failed");
+    }
+    return ret;
+}
+
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/src/Utils.h 
new/sdbus-cpp-1.5.0/src/Utils.h
--- old/sdbus-cpp-1.4.0/src/Utils.h     2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/src/Utils.h     2024-02-26 08:29:35.000000000 +0100
@@ -50,4 +50,38 @@
 #define SDBUS_CHECK_MEMBER_NAME(_NAME)
 #endif
 
+namespace sdbus::internal {
+
+    template <typename _Callable>
+    bool invokeHandlerAndCatchErrors(_Callable callable, sd_bus_error 
*retError)
+    {
+        try
+        {
+            callable();
+        }
+        catch (const Error& e)
+        {
+            sd_bus_error_set(retError, e.getName().c_str(), 
e.getMessage().c_str());
+            return false;
+        }
+        catch (const std::exception& e)
+        {
+            sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, e.what());
+            return false;
+        }
+        catch (...)
+        {
+            sd_bus_error_set(retError, SDBUSCPP_ERROR_NAME, "Unknown error 
occurred");
+            return false;
+        }
+
+        return true;
+    }
+
+    // Implementation of the overload pattern for variant visitation
+    template <class... Ts> struct overload : Ts... { using Ts::operator()...; 
};
+    template <class... Ts> overload(Ts...) -> overload<Ts...>;
+
+}
+
 #endif /* SDBUS_CXX_INTERNAL_UTILS_H_ */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/tests/CMakeLists.txt 
new/sdbus-cpp-1.5.0/tests/CMakeLists.txt
--- old/sdbus-cpp-1.4.0/tests/CMakeLists.txt    2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/tests/CMakeLists.txt    2024-02-26 08:29:35.000000000 
+0100
@@ -106,7 +106,7 @@
 add_executable(sdbus-c++-unit-tests ${UNITTESTS_SRCS})
 target_compile_definitions(sdbus-c++-unit-tests PRIVATE
     LIBSYSTEMD_VERSION=${LIBSYSTEMD_VERSION}
-    SDBUS_HEADER=<${LIBSYSTEMD}/sd-bus.h>)
+    SDBUS_HEADER=<${LIBSYSTEMD_IMPL}/sd-bus.h>)
 target_link_libraries(sdbus-c++-unit-tests sdbus-c++-objlib GTest::gmock)
 
 add_executable(sdbus-c++-integration-tests ${INTEGRATIONTESTS_SRCS})
@@ -140,22 +140,26 @@
 # INSTALLATION
 #----------------------------------
 
-include(GNUInstallDirs)
-set(TESTS_INSTALL_PATH "/opt/test/bin" CACHE STRING "Specifies where the test 
binaries will be installed")
+option(INSTALL_TESTS "Install tests (default OFF)" OFF)
 
-install(TARGETS sdbus-c++-unit-tests DESTINATION ${TESTS_INSTALL_PATH} 
COMPONENT test)
-install(TARGETS sdbus-c++-integration-tests DESTINATION ${TESTS_INSTALL_PATH} 
COMPONENT test)
-install(FILES 
${INTEGRATIONTESTS_SOURCE_DIR}/files/org.sdbuscpp.integrationtests.conf 
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
-
-if(ENABLE_PERF_TESTS)
-    install(TARGETS sdbus-c++-perf-tests-client DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
-    install(TARGETS sdbus-c++-perf-tests-server DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
-    install(FILES ${PERFTESTS_SOURCE_DIR}/files/org.sdbuscpp.perftests.conf 
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
-endif()
+if(INSTALL_TESTS)
+    include(GNUInstallDirs)
+    set(TESTS_INSTALL_PATH "tests/${PROJECT_NAME}" CACHE STRING "Specifies 
where the test binaries will be installed")
+
+    install(TARGETS sdbus-c++-unit-tests DESTINATION ${TESTS_INSTALL_PATH} 
COMPONENT test)
+    install(TARGETS sdbus-c++-integration-tests DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
+    install(FILES 
${INTEGRATIONTESTS_SOURCE_DIR}/files/org.sdbuscpp.integrationtests.conf 
DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
+
+    if(ENABLE_PERF_TESTS)
+        install(TARGETS sdbus-c++-perf-tests-client DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
+        install(TARGETS sdbus-c++-perf-tests-server DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
+        install(FILES 
${PERFTESTS_SOURCE_DIR}/files/org.sdbuscpp.perftests.conf DESTINATION 
${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
+    endif()
 
-if(ENABLE_STRESS_TESTS)
-    install(TARGETS sdbus-c++-stress-tests DESTINATION ${TESTS_INSTALL_PATH} 
COMPONENT test)
-    install(FILES 
${STRESSTESTS_SOURCE_DIR}/files/org.sdbuscpp.stresstests.conf DESTINATION 
${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
+    if(ENABLE_STRESS_TESTS)
+        install(TARGETS sdbus-c++-stress-tests DESTINATION 
${TESTS_INSTALL_PATH} COMPONENT test)
+        install(FILES 
${STRESSTESTS_SOURCE_DIR}/files/org.sdbuscpp.stresstests.conf DESTINATION 
${CMAKE_INSTALL_FULL_SYSCONFDIR}/dbus-1/system.d COMPONENT test)
+    endif()
 endif()
 
 #----------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/sdbus-cpp-1.4.0/tests/integrationtests/DBusGeneralTests.cpp 
new/sdbus-cpp-1.5.0/tests/integrationtests/DBusGeneralTests.cpp
--- old/sdbus-cpp-1.4.0/tests/integrationtests/DBusGeneralTests.cpp     
2023-10-10 19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/tests/integrationtests/DBusGeneralTests.cpp     
2024-02-26 08:29:35.000000000 +0100
@@ -88,6 +88,29 @@
     ASSERT_TRUE(waitUntil(matchingMessageReceived));
 }
 
+TEST_F(AConnection, CanInstallMatchRuleAsynchronously)
+{
+    auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
+    std::atomic<bool> matchingMessageReceived{false};
+    std::atomic<bool> matchRuleInstalled{false};
+    auto slot = s_proxyConnection->addMatchAsync( matchRule
+                                                , [&](sdbus::Message& msg)
+                                                  {
+                                                      if(msg.getPath() == 
OBJECT_PATH)
+                                                          
matchingMessageReceived = true;
+                                                  }
+                                                , [&](sdbus::Message& /*msg*/)
+                                                  {
+                                                      matchRuleInstalled = 
true;
+                                                  } );
+
+    EXPECT_TRUE(waitUntil(matchRuleInstalled));
+
+    m_adaptor->emitSimpleSignal();
+
+    ASSERT_TRUE(waitUntil(matchingMessageReceived));
+}
+
 TEST_F(AConnection, 
WillUnsubscribeMatchRuleWhenClientDestroysTheAssociatedSlot)
 {
     auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/tests/unittests/mocks/SdBusMock.h 
new/sdbus-cpp-1.5.0/tests/unittests/mocks/SdBusMock.h
--- old/sdbus-cpp-1.4.0/tests/unittests/mocks/SdBusMock.h       2023-10-10 
19:26:21.000000000 +0200
+++ new/sdbus-cpp-1.5.0/tests/unittests/mocks/SdBusMock.h       2024-02-26 
08:29:35.000000000 +0100
@@ -71,6 +71,7 @@
     MOCK_METHOD6(sd_bus_add_object_vtable, int(sd_bus *bus, sd_bus_slot 
**slot, const char *path, const char *interface, const sd_bus_vtable *vtable, 
void *userdata));
     MOCK_METHOD3(sd_bus_add_object_manager, int(sd_bus *bus, sd_bus_slot 
**slot, const char *path));
     MOCK_METHOD5(sd_bus_add_match, int(sd_bus *bus, sd_bus_slot **slot, const 
char *match, sd_bus_message_handler_t callback, void *userdata));
+    MOCK_METHOD6(sd_bus_add_match_async, int(sd_bus *bus, sd_bus_slot **slot, 
const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t 
install_callback, void *userdata));
     MOCK_METHOD1(sd_bus_slot_unref, sd_bus_slot*(sd_bus_slot *slot));
 
     MOCK_METHOD1(sd_bus_new, int(sd_bus **ret));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sdbus-cpp-1.4.0/tools/CMakeLists.txt 
new/sdbus-cpp-1.5.0/tools/CMakeLists.txt
--- old/sdbus-cpp-1.4.0/tools/CMakeLists.txt    2023-10-10 19:26:21.000000000 
+0200
+++ new/sdbus-cpp-1.5.0/tools/CMakeLists.txt    2024-02-26 08:29:35.000000000 
+0100
@@ -4,7 +4,7 @@
 
 cmake_minimum_required(VERSION 3.5)
 
-project(sdbus-c++-tools VERSION 1.4.0)
+project(sdbus-c++-tools VERSION 1.5.0)
 
 include(GNUInstallDirs)
 

Reply via email to