From 9e2df02453a6eec788e30de66aa2820ac75958de Mon Sep 17 00:00:00 2001 From: Sotiris Nanopoulos Date: Mon, 7 Dec 2020 16:04:44 -0800 Subject: [PATCH] [Win32 Signals] Add term and ctrl-c signal handlers (#13954) Part 1 of #13188. Adds support for ctrl+c and ctrl+break for Envoy on Windows. The implementation for this following: * On platform_impl we register a CtrlHandler which runs on a separate thread. * On signal_impl we register a read event reader. Thread (1) and (2) communicate via a socket pair and the event is handled on Windows the same way as it is handled on POSIX Signed-off-by: Sotiris Nanopoulos --- .bazelrc | 1 + ci/run_clang_tidy.sh | 2 +- ci/windows_ci_steps.sh | 1 - include/envoy/common/platform.h | 7 ++ include/envoy/event/dispatcher.h | 2 +- source/common/event/BUILD | 51 +++++++++- source/common/event/dispatcher_impl.cc | 2 +- source/common/event/dispatcher_impl.h | 2 +- .../common/event/{ => posix}/signal_impl.cc | 5 +- source/common/event/{ => posix}/signal_impl.h | 3 +- source/common/event/win32/signal_impl.cc | 44 +++++++++ source/common/event/win32/signal_impl.h | 35 +++++++ source/exe/BUILD | 2 + source/exe/win32/platform_impl.cc | 42 +++++++++ source/server/server.cc | 13 +-- test/exe/BUILD | 22 +++++ test/exe/win32_outofproc_main_test.cc | 92 +++++++++++++++++++ test/mocks/event/mocks.h | 4 +- test/mocks/event/wrapped_dispatcher.h | 2 +- 19 files changed, 309 insertions(+), 23 deletions(-) rename source/common/event/{ => posix}/signal_impl.cc (81%) rename source/common/event/{ => posix}/signal_impl.h (81%) create mode 100644 source/common/event/win32/signal_impl.cc create mode 100644 source/common/event/win32/signal_impl.h create mode 100644 test/exe/win32_outofproc_main_test.cc diff --git a/.bazelrc b/.bazelrc index 81a421598fe3..6a7cd55d0524 100644 --- a/.bazelrc +++ b/.bazelrc @@ -298,6 +298,7 @@ build:windows --action_env=TMPDIR build:windows --define signal_trace=disabled build:windows --define hot_restart=disabled build:windows --define tcmalloc=disabled +build:windows --define wasm=disabled build:windows --define manual_stamp=manual_stamp build:windows --cxxopt="/std:c++17" diff --git a/ci/run_clang_tidy.sh b/ci/run_clang_tidy.sh index b29a624c3f45..6412bedc1061 100755 --- a/ci/run_clang_tidy.sh +++ b/ci/run_clang_tidy.sh @@ -31,7 +31,7 @@ echo "Generating compilation database..." # Do not run clang-tidy against win32 impl # TODO(scw00): We should run clang-tidy against win32 impl once we have clang-cl support for Windows function exclude_win32_impl() { - grep -v source/common/filesystem/win32/ | grep -v source/common/common/win32 | grep -v source/exe/win32 | grep -v source/common/api/win32 + grep -v source/common/filesystem/win32/ | grep -v source/common/common/win32 | grep -v source/exe/win32 | grep -v source/common/api/win32 | grep -v source/common/event/win32 } # Do not run clang-tidy against macOS impl diff --git a/ci/windows_ci_steps.sh b/ci/windows_ci_steps.sh index eb2940e9bb95..fd3497e8474d 100755 --- a/ci/windows_ci_steps.sh +++ b/ci/windows_ci_steps.sh @@ -49,7 +49,6 @@ BAZEL_BUILD_OPTIONS=( -c opt --show_task_finish --verbose_failures - --define "wasm=disabled" "--test_output=errors" "${BAZEL_BUILD_EXTRA_OPTIONS[@]}" "${BAZEL_EXTRA_TEST_OPTIONS[@]}") diff --git a/include/envoy/common/platform.h b/include/envoy/common/platform.h index 07bf4319ef2d..ceb6c8b220e7 100644 --- a/include/envoy/common/platform.h +++ b/include/envoy/common/platform.h @@ -65,6 +65,7 @@ typedef uint32_t mode_t; typedef SOCKET os_fd_t; typedef HANDLE filesystem_os_id_t; // NOLINT(modernize-use-using) +typedef DWORD signal_t; // NOLINT(modernize-use-using) typedef unsigned int sa_family_t; @@ -151,6 +152,9 @@ struct msghdr { #define HANDLE_ERROR_PERM ERROR_ACCESS_DENIED #define HANDLE_ERROR_INVALID ERROR_INVALID_HANDLE +#define ENVOY_WIN32_SIGNAL_COUNT 1 +#define ENVOY_SIGTERM 0 + namespace Platform { constexpr absl::string_view null_device_path{"NUL"}; } @@ -215,6 +219,7 @@ constexpr absl::string_view null_device_path{"NUL"}; typedef int os_fd_t; typedef int filesystem_os_id_t; // NOLINT(modernize-use-using) +typedef int signal_t; // NOLINT(modernize-use-using) #define INVALID_HANDLE -1 #define INVALID_SOCKET -1 @@ -245,6 +250,8 @@ typedef int filesystem_os_id_t; // NOLINT(modernize-use-using) #define HANDLE_ERROR_PERM EACCES #define HANDLE_ERROR_INVALID EBADF +#define ENVOY_SIGTERM SIGTERM + namespace Platform { constexpr absl::string_view null_device_path{"/dev/null"}; } diff --git a/include/envoy/event/dispatcher.h b/include/envoy/event/dispatcher.h index bd4e9512aa4b..42048d138f68 100644 --- a/include/envoy/event/dispatcher.h +++ b/include/envoy/event/dispatcher.h @@ -205,7 +205,7 @@ class Dispatcher { * @param cb supplies the callback to invoke when the signal fires. * @return SignalEventPtr a signal event that is owned by the caller. */ - virtual SignalEventPtr listenForSignal(int signal_num, SignalCb cb) PURE; + virtual SignalEventPtr listenForSignal(signal_t signal_num, SignalCb cb) PURE; /** * Posts a functor to the dispatcher. This is safe cross thread. The functor runs in the context diff --git a/source/common/event/BUILD b/source/common/event/BUILD index 99c30f683fc6..c14a6ee08e99 100644 --- a/source/common/event/BUILD +++ b/source/common/event/BUILD @@ -1,6 +1,9 @@ load( "//bazel:envoy_build_system.bzl", "envoy_cc_library", + "envoy_cc_platform_dep", + "envoy_cc_posix_library", + "envoy_cc_win32_library", "envoy_package", ) @@ -13,15 +16,24 @@ envoy_cc_library( srcs = [ "dispatcher_impl.cc", "file_event_impl.cc", - "signal_impl.cc", - ], - hdrs = [ - "signal_impl.h", ], + hdrs = select({ + "//bazel:windows_x86_64": [ + "win32/signal_impl.h", + ], + "//conditions:default": [ + "posix/signal_impl.h", + ], + }), + strip_include_prefix = select({ + "//bazel:windows_x86_64": "win32", + "//conditions:default": "posix", + }), deps = [ ":dispatcher_includes", ":libevent_scheduler_lib", ":real_time_system_lib", + ":signal_lib", "//include/envoy/common:scope_tracker_interface", "//include/envoy/common:time_interface", "//include/envoy/event:signal_interface", @@ -39,6 +51,37 @@ envoy_cc_library( }), ) +envoy_cc_library( + name = "signal_lib", + deps = envoy_cc_platform_dep("signal_impl_lib"), +) + +envoy_cc_posix_library( + name = "signal_impl_lib", + srcs = ["posix/signal_impl.cc"], + hdrs = ["posix/signal_impl.h"], + strip_include_prefix = "posix", + deps = [ + ":dispatcher_includes", + "//include/envoy/event:signal_interface", + "//source/common/common:thread_lib", + ], +) + +envoy_cc_win32_library( + name = "signal_impl_lib", + srcs = ["win32/signal_impl.cc"], + hdrs = ["win32/signal_impl.h"], + strip_include_prefix = "win32", + deps = [ + ":dispatcher_includes", + "//include/envoy/event:signal_interface", + "//source/common/api:os_sys_calls_lib", + "//source/common/common:thread_lib", + "//source/common/network:default_socket_interface_lib", + ], +) + envoy_cc_library( name = "event_impl_base_lib", srcs = ["event_impl_base.cc"], diff --git a/source/common/event/dispatcher_impl.cc b/source/common/event/dispatcher_impl.cc index 382ea30f1d66..2a997a073070 100644 --- a/source/common/event/dispatcher_impl.cc +++ b/source/common/event/dispatcher_impl.cc @@ -218,7 +218,7 @@ void DispatcherImpl::deferredDelete(DeferredDeletablePtr&& to_delete) { void DispatcherImpl::exit() { base_scheduler_.loopExit(); } -SignalEventPtr DispatcherImpl::listenForSignal(int signal_num, SignalCb cb) { +SignalEventPtr DispatcherImpl::listenForSignal(signal_t signal_num, SignalCb cb) { ASSERT(isThreadSafe()); return SignalEventPtr{new SignalEventImpl(*this, signal_num, cb)}; } diff --git a/source/common/event/dispatcher_impl.h b/source/common/event/dispatcher_impl.h index 46de3a8b50f7..7f53c8df942d 100644 --- a/source/common/event/dispatcher_impl.h +++ b/source/common/event/dispatcher_impl.h @@ -71,7 +71,7 @@ class DispatcherImpl : Logger::Loggable, Event::SchedulableCallbackPtr createSchedulableCallback(std::function cb) override; void deferredDelete(DeferredDeletablePtr&& to_delete) override; void exit() override; - SignalEventPtr listenForSignal(int signal_num, SignalCb cb) override; + SignalEventPtr listenForSignal(signal_t signal_num, SignalCb cb) override; void post(std::function callback) override; void run(RunType type) override; Buffer::WatermarkFactory& getWatermarkFactory() override { return *buffer_factory_; } diff --git a/source/common/event/signal_impl.cc b/source/common/event/posix/signal_impl.cc similarity index 81% rename from source/common/event/signal_impl.cc rename to source/common/event/posix/signal_impl.cc index bfd103f73e9e..459e3f9b0dea 100644 --- a/source/common/event/signal_impl.cc +++ b/source/common/event/posix/signal_impl.cc @@ -1,13 +1,12 @@ -#include "common/event/signal_impl.h" - #include "common/event/dispatcher_impl.h" +#include "common/event/signal_impl.h" #include "event2/event.h" namespace Envoy { namespace Event { -SignalEventImpl::SignalEventImpl(DispatcherImpl& dispatcher, int signal_num, SignalCb cb) +SignalEventImpl::SignalEventImpl(DispatcherImpl& dispatcher, signal_t signal_num, SignalCb cb) : cb_(cb) { evsignal_assign( &raw_event_, &dispatcher.base(), signal_num, diff --git a/source/common/event/signal_impl.h b/source/common/event/posix/signal_impl.h similarity index 81% rename from source/common/event/signal_impl.h rename to source/common/event/posix/signal_impl.h index 2e358834b5f3..b2d6014b041a 100644 --- a/source/common/event/signal_impl.h +++ b/source/common/event/posix/signal_impl.h @@ -13,11 +13,10 @@ namespace Event { */ class SignalEventImpl : public SignalEvent, ImplBase { public: - SignalEventImpl(DispatcherImpl& dispatcher, int signal_num, SignalCb cb); + SignalEventImpl(DispatcherImpl& dispatcher, signal_t signal_num, SignalCb cb); private: SignalCb cb_; }; - } // namespace Event } // namespace Envoy diff --git a/source/common/event/win32/signal_impl.cc b/source/common/event/win32/signal_impl.cc new file mode 100644 index 000000000000..4ffd62b73094 --- /dev/null +++ b/source/common/event/win32/signal_impl.cc @@ -0,0 +1,44 @@ +#include "common/api/os_sys_calls_impl.h" +#include "common/event/dispatcher_impl.h" +#include "common/event/signal_impl.h" + +#include "event2/event.h" + +namespace Envoy { +namespace Event { + +SignalEventImpl::SignalEventImpl(DispatcherImpl& dispatcher, signal_t signal_num, SignalCb cb) + : cb_(cb) { + + if (signal_num > eventBridgeHandlersSingleton::get().size()) { + PANIC("Attempting to create SignalEventImpl with a signal id that exceeds the number of " + "supported signals."); + } + + if (eventBridgeHandlersSingleton::get()[signal_num]) { + return; + } + os_fd_t socks[2]; + Api::SysCallIntResult result = + Api::OsSysCallsSingleton::get().socketpair(AF_INET, SOCK_STREAM, IPPROTO_TCP, socks); + ASSERT(result.rc_ == 0); + + read_handle_ = std::make_unique(socks[0], false, AF_INET); + result = read_handle_->setBlocking(false); + ASSERT(result.rc_ == 0); + auto write_handle = std::make_shared(socks[1], false, AF_INET); + result = write_handle->setBlocking(false); + ASSERT(result.rc_ == 0); + + read_handle_->initializeFileEvent( + dispatcher, + [this](uint32_t events) -> void { + ASSERT(events == Event::FileReadyType::Read); + cb_(); + }, + Event::FileTriggerType::Level, Event::FileReadyType::Read); + eventBridgeHandlersSingleton::get()[signal_num] = write_handle; +} + +} // namespace Event +} // namespace Envoy diff --git a/source/common/event/win32/signal_impl.h b/source/common/event/win32/signal_impl.h new file mode 100644 index 000000000000..51e21e4f1ec9 --- /dev/null +++ b/source/common/event/win32/signal_impl.h @@ -0,0 +1,35 @@ +#pragma once + +#include "envoy/event/signal.h" +#include "envoy/network/io_handle.h" + +#include "common/event/dispatcher_impl.h" +#include "common/event/event_impl_base.h" +#include "common/network/io_socket_handle_impl.h" +#include "common/singleton/threadsafe_singleton.h" + +#include "absl/container/flat_hash_map.h" + +namespace Envoy { +namespace Event { + +/** + * libevent implementation of Event::SignalEvent. + */ +class SignalEventImpl : public SignalEvent { +public: + SignalEventImpl(DispatcherImpl& dispatcher, signal_t signal_num, SignalCb cb); + +private: + SignalCb cb_; + Network::IoHandlePtr read_handle_; +}; + +// Windows ConsoleControlHandler does not allow for a context. As a result the thread +// spawned to handle the console events communicates with the main program with this socketpair. +// Here we have a map from signal types to IoHandle. When we write to this handle we trigger an +// event that notifies Envoy to act on the signal. +using eventBridgeHandlersSingleton = + ThreadSafeSingleton, ENVOY_WIN32_SIGNAL_COUNT>>; +} // namespace Event +} // namespace Envoy diff --git a/source/exe/BUILD b/source/exe/BUILD index 3edb3dd917c2..1b8bc64bbcb5 100644 --- a/source/exe/BUILD +++ b/source/exe/BUILD @@ -168,8 +168,10 @@ envoy_cc_win32_library( srcs = ["win32/platform_impl.cc"], deps = [ ":platform_header_lib", + "//source/common/buffer:buffer_lib", "//source/common/common:assert_lib", "//source/common/common:thread_lib", + "//source/common/event:signal_lib", "//source/common/filesystem:filesystem_lib", ], ) diff --git a/source/exe/win32/platform_impl.cc b/source/exe/win32/platform_impl.cc index ffedb3f478f6..52107ae546fe 100644 --- a/source/exe/win32/platform_impl.cc +++ b/source/exe/win32/platform_impl.cc @@ -1,17 +1,59 @@ +#include +#include + +#include "common/buffer/buffer_impl.h" #include "common/common/assert.h" #include "common/common/thread_impl.h" +#include "common/event/signal_impl.h" #include "common/filesystem/filesystem_impl.h" #include "exe/platform_impl.h" namespace Envoy { +static std::atomic shutdown_pending = false; + +BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) { + if (shutdown_pending) { + return 0; + } + shutdown_pending = true; + + auto handler = Event::eventBridgeHandlersSingleton::get()[ENVOY_SIGTERM]; + if (!handler) { + return 0; + } + + // This code is executed as part of a thread running under a thread owned and + // managed by Windows console host. For that reason we want to avoid allocating + // substantial amount of memory or taking locks. + // This is why we write to a socket to wake up the signal handler. + char data[] = {'a'}; + Buffer::RawSlice buffer{data, 1}; + auto result = handler->writev(&buffer, 1); + RELEASE_ASSERT(result.rc_ == 1, + fmt::format("failed to write 1 byte: {}", result.err_->getErrorDetails())); + + if (fdwCtrlType == CTRL_LOGOFF_EVENT || fdwCtrlType == CTRL_SHUTDOWN_EVENT) { + // These events terminate the process immediately so we want to give a couple of seconds + // to the dispatcher to shutdown the server. + constexpr size_t delay = 3; + absl::SleepFor(absl::Seconds(delay)); + } + return 1; +} + PlatformImpl::PlatformImpl() : thread_factory_(std::make_unique()), file_system_(std::make_unique()) { WSADATA wsa_data; const WORD version_requested = MAKEWORD(2, 2); RELEASE_ASSERT(WSAStartup(version_requested, &wsa_data) == 0, "WSAStartup failed with error"); + + if (!SetConsoleCtrlHandler(CtrlHandler, 1)) { + // The Control Handler is executing in a different thread. + ENVOY_LOG_MISC(warn, "Could not set Windows Control Handlers. Continuing without them."); + } } PlatformImpl::~PlatformImpl() { ::WSACleanup(); } diff --git a/source/server/server.cc b/source/server/server.cc index 59e9220583af..7bc011a679a8 100644 --- a/source/server/server.cc +++ b/source/server/server.cc @@ -648,15 +648,16 @@ RunHelper::RunHelper(Instance& instance, const Options& options, Event::Dispatch } }) { // Setup signals. + // Since signals are not supported on Windows we have an internal definition for `SIGTERM` + // On POSIX it resolves as expected to SIGTERM + // On Windows we use it internally for all the console events that indicate that we should + // terminate the process. if (options.signalHandlingEnabled()) { -// TODO(Pivotal): Figure out solution to graceful shutdown on Windows. None of these signals exist -// on Windows. -#ifndef WIN32 - sigterm_ = dispatcher.listenForSignal(SIGTERM, [&instance]() { - ENVOY_LOG(warn, "caught SIGTERM"); + sigterm_ = dispatcher.listenForSignal(ENVOY_SIGTERM, [&instance]() { + ENVOY_LOG(warn, "caught ENVOY_SIGTERM"); instance.shutdown(); }); - +#ifndef WIN32 sigint_ = dispatcher.listenForSignal(SIGINT, [&instance]() { ENVOY_LOG(warn, "caught SIGINT"); instance.shutdown(); diff --git a/test/exe/BUILD b/test/exe/BUILD index 74178f65337c..a73ee1f01e5e 100644 --- a/test/exe/BUILD +++ b/test/exe/BUILD @@ -84,3 +84,25 @@ envoy_cc_test( "//test/test_common:utility_lib", ], ) + +# Due to the limitiations of how Windows signals work +# this test cannot be executed through bazel and it must +# be executed as a standalone executable. +# e.g.: `./bazel-bin/test/exe/win32_outofproc_main_test.exe` +envoy_cc_test( + name = "win32_outofproc_main_test", + srcs = ["win32_outofproc_main_test.cc"], + data = [ + "//source/exe:envoy-static", + "//test/config/integration:google_com_proxy_port_0", + ], + # TODO(envoyproxy/windows-dev): Disable the manual tag. + tags = ["manual"], + deps = [ + "//source/common/api:api_lib", + "//source/exe:main_common_lib", + "//test/mocks/runtime:runtime_mocks", + "//test/test_common:contention_lib", + "//test/test_common:environment_lib", + ], +) diff --git a/test/exe/win32_outofproc_main_test.cc b/test/exe/win32_outofproc_main_test.cc new file mode 100644 index 000000000000..529d77fa758b --- /dev/null +++ b/test/exe/win32_outofproc_main_test.cc @@ -0,0 +1,92 @@ +#include + +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { + +#ifdef WIN32 +class MainCommonTest : public testing::TestWithParam { +protected: + MainCommonTest() + : config_file_(TestEnvironment::temporaryFileSubstitute( + "test/config/integration/google_com_proxy_port_0.yaml", TestEnvironment::ParamMap(), + TestEnvironment::PortMap(), GetParam())), + envoy_exe_(TestEnvironment::runfilesPath("source/exe/envoy-static.exe")) {} + + void cleanup() { + UINT uExitCode = 0; + TerminateProcess(piProcInfo_.hProcess, uExitCode); + remove(log_path_.c_str()); + } + + void sendSingal(DWORD pid, DWORD signal) { + EXPECT_TRUE(FreeConsole()) << fmt::format("Failed to FreeConsole, error {}", GetLastError()); + EXPECT_TRUE(AttachConsole(pid)) + << fmt::format("Failed to AttachConsole, error {}", GetLastError()); + EXPECT_TRUE(SetConsoleCtrlHandler(NULL, 1)) + << fmt::format("Failed to SetConsoleCtrlHandler, error {}", GetLastError()); + EXPECT_TRUE(GenerateConsoleCtrlEvent(signal, pid)) + << fmt::format("Failed to GenerateConsoleCtrlEvent, error {}", GetLastError()); + } + + void createEnvoyProcess() { + STARTUPINFO siStartInfo; + ZeroMemory(&siStartInfo, sizeof(siStartInfo)); + log_path_ = TestEnvironment::temporaryDirectory() + "/output.txt"; + ZeroMemory(&piProcInfo_, sizeof(PROCESS_INFORMATION)); + auto commandLine = fmt::format("{} --config-path {} -l warn --log-path {}", envoy_exe_, + config_file_, log_path_); + ENVOY_LOG_MISC(warn, commandLine); + BOOL bSuccess = CreateProcessA(NULL, + const_cast(commandLine.c_str()), // command line + NULL, // process security attributes + NULL, // primary thread security attributes + 1, // handles are inherited + CREATE_NEW_PROCESS_GROUP, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // `STARTUPINFO` pointer + &piProcInfo_); // receives `PROCESS_INFORMATION` + EXPECT_TRUE(bSuccess) << fmt::format("Failed to create Envoy process, error {}", + GetLastError()); + } + + std::string config_file_; + std::string envoy_exe_; + PROCESS_INFORMATION piProcInfo_; + std::string log_path_; +}; + +INSTANTIATE_TEST_SUITE_P(IpVersions, MainCommonTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + +TEST_P(MainCommonTest, EnvoyHandlesCtrlBreakEvent) { + createEnvoyProcess(); + ENVOY_LOG_MISC(warn, "Envoy process with pid {}", piProcInfo_.dwProcessId); + Sleep(2 * 1000); + sendSingal(piProcInfo_.dwProcessId, CTRL_BREAK_EVENT); + size_t total_sleep = 1; + constexpr size_t resonable_sleep_time = 5; + DWORD exitCode; + do { + Sleep(total_sleep * 1000); + ++total_sleep; + GetExitCodeProcess(piProcInfo_.hProcess, &exitCode); + } while (exitCode == STILL_ACTIVE && total_sleep <= resonable_sleep_time); + EXPECT_TRUE(total_sleep <= resonable_sleep_time); + auto output = TestEnvironment::readFileToStringForTest(log_path_); + size_t count = 0; + for (size_t pos = 0; (pos = output.find("ENVOY_SIGTERM", pos)) != std::string::npos; + ++pos, ++count) { + } + EXPECT_EQ(1, count); + ENVOY_LOG_MISC(warn, "Envoy output {}", output); + cleanup(); +} +#endif + +} // namespace Envoy \ No newline at end of file diff --git a/test/mocks/event/mocks.h b/test/mocks/event/mocks.h index 957f06222521..8aad73db5a32 100644 --- a/test/mocks/event/mocks.h +++ b/test/mocks/event/mocks.h @@ -97,7 +97,7 @@ class MockDispatcher : public Dispatcher { } } - SignalEventPtr listenForSignal(int signal_num, SignalCb cb) override { + SignalEventPtr listenForSignal(signal_t signal_num, SignalCb cb) override { return SignalEventPtr{listenForSignal_(signal_num, cb)}; } @@ -127,7 +127,7 @@ class MockDispatcher : public Dispatcher { MOCK_METHOD(SchedulableCallback*, createSchedulableCallback_, (std::function cb)); MOCK_METHOD(void, deferredDelete_, (DeferredDeletable * to_delete)); MOCK_METHOD(void, exit, ()); - MOCK_METHOD(SignalEvent*, listenForSignal_, (int signal_num, SignalCb cb)); + MOCK_METHOD(SignalEvent*, listenForSignal_, (signal_t signal_num, SignalCb cb)); MOCK_METHOD(void, post, (std::function callback)); MOCK_METHOD(void, run, (RunType type)); MOCK_METHOD(const ScopeTrackedObject*, setTrackedObject, (const ScopeTrackedObject* object)); diff --git a/test/mocks/event/wrapped_dispatcher.h b/test/mocks/event/wrapped_dispatcher.h index 74e935328984..974d61b39be2 100644 --- a/test/mocks/event/wrapped_dispatcher.h +++ b/test/mocks/event/wrapped_dispatcher.h @@ -88,7 +88,7 @@ class WrappedDispatcher : public Dispatcher { void exit() override { impl_.exit(); } - SignalEventPtr listenForSignal(int signal_num, SignalCb cb) override { + SignalEventPtr listenForSignal(signal_t signal_num, SignalCb cb) override { return impl_.listenForSignal(signal_num, std::move(cb)); }