From e66c12105b653b7eeeeda4f3fb9e0a17338e3b68 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 18:41:38 +0200 Subject: [PATCH 01/18] lib/sqlite/meson.build: add missing external dependency on libsqlite --- src/lib/sqlite/meson.build | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/sqlite/meson.build b/src/lib/sqlite/meson.build index 6a5d07ef5..9de67fcfa 100644 --- a/src/lib/sqlite/meson.build +++ b/src/lib/sqlite/meson.build @@ -21,4 +21,7 @@ sqlite = static_library( sqlite_dep = declare_dependency( link_with: sqlite, + dependencies: [ + sqlite_dep, + ], ) From fd82d67678a835749d12055d32835b92a7e84194 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 18:45:18 +0200 Subject: [PATCH 02/18] sticker/Database: pass NarrowPath to sqlite3_open() Closes https://github.com/MusicPlayerDaemon/MPD/issues/1171 --- NEWS | 2 ++ src/sticker/Database.cxx | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a57a408bd..9883f913b 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.22.9 (not yet released) +* Windows + - fix build failure with SQLite ver 0.22.8 (2021/05/22) * fix crash bug in "albumart" command (0.22.7 regression) diff --git a/src/sticker/Database.cxx b/src/sticker/Database.cxx index 860b40dd3..a39cfc93a 100644 --- a/src/sticker/Database.cxx +++ b/src/sticker/Database.cxx @@ -21,6 +21,7 @@ #include "Sticker.hxx" #include "lib/sqlite/Util.hxx" #include "fs/Path.hxx" +#include "fs/NarrowPath.hxx" #include "Idle.hxx" #include "util/StringCompare.hxx" #include "util/ScopeExit.hxx" @@ -82,7 +83,7 @@ static const char sticker_sql_create[] = ""; StickerDatabase::StickerDatabase(Path path) - :db(path.c_str()) + :db(NarrowPath(path)) { assert(!path.IsNull()); From 3488a47c415d6b93936f89bec596d9b51c2cf5aa Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 18:37:51 +0200 Subject: [PATCH 03/18] subprojects/sqlite3.wrap: add SQLite wrap --- src/lib/sqlite/meson.build | 4 +++- subprojects/.gitignore | 1 + subprojects/sqlite3.wrap | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 subprojects/sqlite3.wrap diff --git a/src/lib/sqlite/meson.build b/src/lib/sqlite/meson.build index 9de67fcfa..2db7fc8ae 100644 --- a/src/lib/sqlite/meson.build +++ b/src/lib/sqlite/meson.build @@ -1,5 +1,7 @@ if enable_database - sqlite_dep = dependency('sqlite3', version: '>= 3.7.3', required: get_option('sqlite')) + sqlite_dep = dependency('sqlite3', version: '>= 3.7.3', + fallback: ['sqlite3', 'sqlite3_dep'], + required: get_option('sqlite')) else sqlite_dep = dependency('', required: false) endif diff --git a/subprojects/.gitignore b/subprojects/.gitignore index e6f228fa3..a4c73fa2b 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -1,3 +1,4 @@ /packagecache/ /googletest-*/ +/sqlite-*/ diff --git a/subprojects/sqlite3.wrap b/subprojects/sqlite3.wrap new file mode 100644 index 000000000..4d51dc053 --- /dev/null +++ b/subprojects/sqlite3.wrap @@ -0,0 +1,12 @@ +[wrap-file] +directory = sqlite-amalgamation-3340100 +source_url = https://www.sqlite.org/2021/sqlite-amalgamation-3340100.zip +source_filename = sqlite-amalgamation-3340100.zip +source_hash = e0b1c0345fe4338b936e17da8e1bd88366cd210e576834546977f040c12a8f68 +patch_url = https://wrapdb.mesonbuild.com/v1/projects/sqlite3/3.34.1/1/get_zip +patch_filename = sqlite3-3.34.1-1-wrap.zip +patch_hash = cba9e47bdb4c02f88fadaae8deab357218d32562c6b86ce7ba0c72f107044360 + +[provide] +sqlite3 = sqlite3_dep + From 1bc02123f901e141f84ff484bf90bafdbe770c28 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:00:36 +0200 Subject: [PATCH 04/18] meson.build: remove "-pedantic", implied by Meson Meson adds "-Wpedantic" in warning_level 3 (which is MPD's default). --- meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/meson.build b/meson.build index 5071384ab..7806d837b 100644 --- a/meson.build +++ b/meson.build @@ -92,7 +92,6 @@ test_cflags = test_common_flags + [ '-Wstrict-prototypes', '-Wcast-qual', '-Wwrite-strings', - '-pedantic', ] test_ldflags = [ From 02502514f68197925ac155ff62b59b00b18dd450 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:05:57 +0200 Subject: [PATCH 05/18] meson.build: require clang 7 (remove bug workaround) --- doc/user.rst | 2 +- meson.build | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/doc/user.rst b/doc/user.rst index fe4825a4d..1bc8f6158 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -55,7 +55,7 @@ and unpack it (or `clone the git repository In any case, you need: -* a C++17 compiler (e.g. GCC 8 or clang 5) +* a C++17 compiler (e.g. GCC 8 or clang 7) * `Meson 0.49.0 `__ and `Ninja `__ * Boost 1.58 diff --git a/meson.build b/meson.build index 7806d837b..b9b77ce76 100644 --- a/meson.build +++ b/meson.build @@ -24,8 +24,8 @@ c_compiler = meson.get_compiler('c') if compiler.get_id() == 'gcc' and compiler.version().version_compare('<8') warning('Your GCC version is too old. You need at least version 8.') -elif compiler.get_id() == 'clang' and compiler.version().version_compare('<5') - warning('Your clang version is too old. You need at least version 5.') +elif compiler.get_id() == 'clang' and compiler.version().version_compare('<7') + warning('Your clang version is too old. You need at least version 7.') endif version_conf = configuration_data() @@ -79,12 +79,6 @@ test_cxxflags = test_common_flags + [ '-Wno-non-virtual-dtor', ] -if compiler.get_id() == 'clang' - # Workaround for clang bug - # https://bugs.llvm.org/show_bug.cgi?id=32611 - test_cxxflags += '-funwind-tables' -endif - test_cflags = test_common_flags + [ '-Wmissing-prototypes', '-Wshadow', From 281270cd2ad1aa60968275cf62a9cc1dd1ce56f2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:03:10 +0200 Subject: [PATCH 06/18] meson.build: remove unused variables common_cflags, common_cxxflags --- meson.build | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index b9b77ce76..526980bdc 100644 --- a/meson.build +++ b/meson.build @@ -42,12 +42,6 @@ common_cppflags = [ '-D_GNU_SOURCE', ] -common_cflags = [ -] - -common_cxxflags = [ -] - test_common_flags = [ '-Wvla', '-Wdouble-promotion', @@ -120,8 +114,8 @@ if get_option('fuzzer') add_global_link_arguments(fuzzer_flags, language: 'cpp') endif -add_global_arguments(common_cxxflags + compiler.get_supported_arguments(test_cxxflags), language: 'cpp') -add_global_arguments(common_cflags + c_compiler.get_supported_arguments(test_cflags), language: 'c') +add_global_arguments(compiler.get_supported_arguments(test_cxxflags), language: 'cpp') +add_global_arguments(c_compiler.get_supported_arguments(test_cflags), language: 'c') add_global_link_arguments(compiler.get_supported_link_arguments(test_ldflags), language: 'cpp') is_linux = host_machine.system() == 'linux' From 48c7c540df7ae65eae099525c3e314d3035a2b5b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 20:49:27 +0200 Subject: [PATCH 07/18] meson.build: use add_project_arguments() instead of add_global_arguments() Don't propagate MPD-specific compiler flags to subprojects. --- meson.build | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/meson.build b/meson.build index 526980bdc..2d921e764 100644 --- a/meson.build +++ b/meson.build @@ -42,16 +42,24 @@ common_cppflags = [ '-D_GNU_SOURCE', ] +test_global_common_flags = [ + '-fvisibility=hidden', +] + test_common_flags = [ '-Wvla', '-Wdouble-promotion', - '-fvisibility=hidden', - '-ffast-math', '-ftree-vectorize', ] +test_global_cxxflags = test_global_common_flags + [ +] + +test_global_cflags = test_global_common_flags + [ +] + test_cxxflags = test_common_flags + [ '-fno-threadsafe-statics', '-fmerge-all-constants', @@ -91,11 +99,11 @@ test_ldflags = [ ] if get_option('buildtype') != 'debug' - test_cxxflags += [ + test_global_cxxflags += [ '-ffunction-sections', '-fdata-sections', ] - test_cflags += [ + test_global_cflags += [ '-ffunction-sections', '-fdata-sections', ] @@ -114,9 +122,11 @@ if get_option('fuzzer') add_global_link_arguments(fuzzer_flags, language: 'cpp') endif -add_global_arguments(compiler.get_supported_arguments(test_cxxflags), language: 'cpp') -add_global_arguments(c_compiler.get_supported_arguments(test_cflags), language: 'c') -add_global_link_arguments(compiler.get_supported_link_arguments(test_ldflags), language: 'cpp') +add_global_arguments(compiler.get_supported_arguments(test_global_cxxflags), language: 'cpp') +add_global_arguments(c_compiler.get_supported_arguments(test_global_cflags), language: 'c') +add_project_arguments(compiler.get_supported_arguments(test_cxxflags), language: 'cpp') +add_project_arguments(c_compiler.get_supported_arguments(test_cflags), language: 'c') +add_project_link_arguments(compiler.get_supported_link_arguments(test_ldflags), language: 'cpp') is_linux = host_machine.system() == 'linux' is_android = get_option('android_ndk') != '' From dd10b2bd61db9b20f39a839ff22c76a8f0c70e48 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:24:42 +0200 Subject: [PATCH 08/18] meson.build: remove warning options implied by -Wall -Wextra --- meson.build | 3 --- 1 file changed, 3 deletions(-) diff --git a/meson.build b/meson.build index 2d921e764..910f52928 100644 --- a/meson.build +++ b/meson.build @@ -66,10 +66,8 @@ test_cxxflags = test_common_flags + [ '-Wmissing-declarations', '-Wshadow', - '-Wpointer-arith', '-Wcast-qual', '-Wwrite-strings', - '-Wsign-compare', '-Wcomma', '-Wextra-semi', '-Wheader-hygiene', @@ -84,7 +82,6 @@ test_cxxflags = test_common_flags + [ test_cflags = test_common_flags + [ '-Wmissing-prototypes', '-Wshadow', - '-Wpointer-arith', '-Wstrict-prototypes', '-Wcast-qual', '-Wwrite-strings', From dad1c21b59b123075c7fec48acf47c2fc8471e90 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:32:23 +0200 Subject: [PATCH 09/18] zeroconf/avahi: move variable declaration into "case" --- src/zeroconf/ZeroconfAvahi.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/zeroconf/ZeroconfAvahi.cxx b/src/zeroconf/ZeroconfAvahi.cxx index 466a29351..29e5f7ba8 100644 --- a/src/zeroconf/ZeroconfAvahi.cxx +++ b/src/zeroconf/ZeroconfAvahi.cxx @@ -157,8 +157,6 @@ MyAvahiClientCallback(AvahiClient *c, AvahiClientState state, FormatDebug(avahi_domain, "Client changed to state %d", state); switch (state) { - int reason; - case AVAHI_CLIENT_S_RUNNING: LogDebug(avahi_domain, "Client is RUNNING"); @@ -169,8 +167,8 @@ MyAvahiClientCallback(AvahiClient *c, AvahiClientState state, break; case AVAHI_CLIENT_FAILURE: - reason = avahi_client_errno(c); - if (reason == AVAHI_ERR_DISCONNECTED) { + if (int reason = avahi_client_errno(c); + reason == AVAHI_ERR_DISCONNECTED) { LogNotice(avahi_domain, "Client Disconnected, will reconnect shortly"); if (avahi_group != nullptr) { From 8c690fb737052c7292367613b83f482803c70cc4 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:31:42 +0200 Subject: [PATCH 10/18] decoder/mad: move variable declaration into "case" --- src/decoder/plugins/MadDecoderPlugin.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/decoder/plugins/MadDecoderPlugin.cxx b/src/decoder/plugins/MadDecoderPlugin.cxx index 8fb99a0cd..7b6c98eec 100644 --- a/src/decoder/plugins/MadDecoderPlugin.cxx +++ b/src/decoder/plugins/MadDecoderPlugin.cxx @@ -889,8 +889,6 @@ inline bool MadDecoder::HandleCurrentFrame() noexcept { switch (mute_frame) { - DecoderCommand cmd; - case MadDecoderMuteFrame::SKIP: mute_frame = MadDecoderMuteFrame::NONE; break; @@ -899,8 +897,8 @@ MadDecoder::HandleCurrentFrame() noexcept mute_frame = MadDecoderMuteFrame::NONE; UpdateTimerNextFrame(); break; - case MadDecoderMuteFrame::NONE: - cmd = SynthAndSubmit(); + case MadDecoderMuteFrame::NONE: { + const auto cmd = SynthAndSubmit(); UpdateTimerNextFrame(); if (cmd == DecoderCommand::SEEK) { assert(input_stream.IsSeekable()); @@ -922,6 +920,7 @@ MadDecoder::HandleCurrentFrame() noexcept } else if (cmd != DecoderCommand::NONE) return false; } + } return true; } From c1e25378517fefbb1fda747b726e6d6b8f5459b8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:37:10 +0200 Subject: [PATCH 11/18] meson.build: add comment for clang-only warning options --- meson.build | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/meson.build b/meson.build index 910f52928..fcd08dc14 100644 --- a/meson.build +++ b/meson.build @@ -68,15 +68,18 @@ test_cxxflags = test_common_flags + [ '-Wshadow', '-Wcast-qual', '-Wwrite-strings', - '-Wcomma', + '-Wextra-semi', + '-Wunused', + + '-Wno-non-virtual-dtor', + + # clang specific warning options: + '-Wcomma', '-Wheader-hygiene', '-Winconsistent-missing-destructor-override', '-Wunreachable-code-break', - '-Wunused', '-Wused-but-marked-unused', - - '-Wno-non-virtual-dtor', ] test_cflags = test_common_flags + [ From 6aeb0e335b2c1bc0003307b088c939da8a9026d3 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:47:57 +0200 Subject: [PATCH 12/18] meson.build: add comment for -Wno-non-virtual-dtor --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index fcd08dc14..a11b88324 100644 --- a/meson.build +++ b/meson.build @@ -72,6 +72,7 @@ test_cxxflags = test_common_flags + [ '-Wextra-semi', '-Wunused', + # a vtable without a dtor is just fine '-Wno-non-virtual-dtor', # clang specific warning options: From 1375dcc4ec616a106f2bee01d9eb8c7cabd1d903 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:47:09 +0200 Subject: [PATCH 13/18] meson.build: sort warning options --- meson.build | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index a11b88324..f589b6ce0 100644 --- a/meson.build +++ b/meson.build @@ -64,13 +64,12 @@ test_cxxflags = test_common_flags + [ '-fno-threadsafe-statics', '-fmerge-all-constants', + '-Wcast-qual', + '-Wextra-semi', '-Wmissing-declarations', '-Wshadow', - '-Wcast-qual', - '-Wwrite-strings', - - '-Wextra-semi', '-Wunused', + '-Wwrite-strings', # a vtable without a dtor is just fine '-Wno-non-virtual-dtor', @@ -84,10 +83,10 @@ test_cxxflags = test_common_flags + [ ] test_cflags = test_common_flags + [ + '-Wcast-qual', '-Wmissing-prototypes', '-Wshadow', '-Wstrict-prototypes', - '-Wcast-qual', '-Wwrite-strings', ] From 0b0acb3981dc7f5fc855ce17db223cb480c88735 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 21:30:04 +0200 Subject: [PATCH 14/18] meson.build: add more C++ warning flags --- meson.build | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f589b6ce0..b4ce86e04 100644 --- a/meson.build +++ b/meson.build @@ -65,10 +65,17 @@ test_cxxflags = test_common_flags + [ '-fmerge-all-constants', '-Wcast-qual', + '-Wcomma-subscript', '-Wextra-semi', + '-Wmismatched-tags', '-Wmissing-declarations', + '-Woverloaded-virtual', '-Wshadow', + '-Wsign-promo', + '-Wsuggest-override', '-Wunused', + '-Wvolatile', + '-Wvirtual-inheritance', '-Wwrite-strings', # a vtable without a dtor is just fine @@ -78,7 +85,7 @@ test_cxxflags = test_common_flags + [ '-Wcomma', '-Wheader-hygiene', '-Winconsistent-missing-destructor-override', - '-Wunreachable-code-break', + '-Wunreachable-code-aggressive', '-Wused-but-marked-unused', ] From 56c0733b427b444beebb9e1a85d5082a20e2a72b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 22:22:40 +0200 Subject: [PATCH 15/18] meson.build: disable -Wsuggest-override with GCC 8 --- meson.build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index b4ce86e04..5ba58c5b8 100644 --- a/meson.build +++ b/meson.build @@ -72,7 +72,6 @@ test_cxxflags = test_common_flags + [ '-Woverloaded-virtual', '-Wshadow', '-Wsign-promo', - '-Wsuggest-override', '-Wunused', '-Wvolatile', '-Wvirtual-inheritance', @@ -89,6 +88,12 @@ test_cxxflags = test_common_flags + [ '-Wused-but-marked-unused', ] +if compiler.get_id() != 'gcc' or compiler.version().version_compare('>=9') + # The GCC 8 implementation of this flag is buggy: it complains even + # if "final" is present, which implies "override". + test_cxxflags += '-Wsuggest-override' +endif + test_cflags = test_common_flags + [ '-Wcast-qual', '-Wmissing-prototypes', From 0cef84cac6b2f3c45b451cb2a011620ba5ca3749 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 22:15:27 +0200 Subject: [PATCH 16/18] zeroconf/AvahiPoll: rename "timer" to "event" --- src/zeroconf/AvahiPoll.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/zeroconf/AvahiPoll.cxx b/src/zeroconf/AvahiPoll.cxx index 8818c298a..41c3e4e54 100644 --- a/src/zeroconf/AvahiPoll.cxx +++ b/src/zeroconf/AvahiPoll.cxx @@ -78,7 +78,7 @@ private: }; struct AvahiTimeout final { - TimerEvent timer; + TimerEvent event; const AvahiTimeoutCallback callback; void *const userdata; @@ -87,17 +87,17 @@ public: AvahiTimeout(const struct timeval *tv, AvahiTimeoutCallback _callback, void *_userdata, EventLoop &_loop) - :timer(_loop, BIND_THIS_METHOD(OnTimeout)), + :event(_loop, BIND_THIS_METHOD(OnTimeout)), callback(_callback), userdata(_userdata) { if (tv != nullptr) - timer.Schedule(ToSteadyClockDuration(*tv)); + event.Schedule(ToSteadyClockDuration(*tv)); } static void TimeoutUpdate(AvahiTimeout *t, const struct timeval *tv) { if (tv != nullptr) - t->timer.Schedule(ToSteadyClockDuration(*tv)); + t->event.Schedule(ToSteadyClockDuration(*tv)); else - t->timer.Cancel(); + t->event.Cancel(); } static void TimeoutFree(AvahiTimeout *t) { From bce144a232d37547763d180bc43422f1963d4255 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 22:14:27 +0200 Subject: [PATCH 17/18] zeroconf/AvahiPoll: move code to Schedule() --- src/zeroconf/AvahiPoll.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/zeroconf/AvahiPoll.cxx b/src/zeroconf/AvahiPoll.cxx index 41c3e4e54..1a81d3580 100644 --- a/src/zeroconf/AvahiPoll.cxx +++ b/src/zeroconf/AvahiPoll.cxx @@ -90,12 +90,12 @@ public: :event(_loop, BIND_THIS_METHOD(OnTimeout)), callback(_callback), userdata(_userdata) { if (tv != nullptr) - event.Schedule(ToSteadyClockDuration(*tv)); + Schedule(*tv); } static void TimeoutUpdate(AvahiTimeout *t, const struct timeval *tv) { if (tv != nullptr) - t->event.Schedule(ToSteadyClockDuration(*tv)); + t->Schedule(*tv); else t->event.Cancel(); } @@ -105,6 +105,10 @@ public: } private: + void Schedule(const struct timeval &tv) noexcept { + event.Schedule(ToSteadyClockDuration(tv)); + } + void OnTimeout() noexcept { callback(this, userdata); } From 7a6823dcdfc7056d3c0e93f31aea49a99a2fddd9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 May 2021 22:17:10 +0200 Subject: [PATCH 18/18] zeroconf/AvahiPoll: the struct timeval is an absolute time point Fixes broken libavahi-client timeouts. --- src/zeroconf/AvahiPoll.cxx | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/zeroconf/AvahiPoll.cxx b/src/zeroconf/AvahiPoll.cxx index 1a81d3580..2852847ef 100644 --- a/src/zeroconf/AvahiPoll.cxx +++ b/src/zeroconf/AvahiPoll.cxx @@ -105,8 +105,28 @@ public: } private: + [[gnu::pure]] + Event::Duration AbsoluteToDuration(const struct timeval &tv) noexcept { + if (tv.tv_sec == 0) + /* schedule immediately */ + return {}; + + struct timeval now; + if (gettimeofday(&now, nullptr) < 0) + /* shouldn't ever fail, but if it does, do + something reasonable */ + return std::chrono::seconds(1); + + auto d = ToSteadyClockDuration(tv) + - ToSteadyClockDuration(now); + if (d.count() < 0) + return {}; + + return d; + } + void Schedule(const struct timeval &tv) noexcept { - event.Schedule(ToSteadyClockDuration(tv)); + event.Schedule(AbsoluteToDuration(tv)); } void OnTimeout() noexcept {