已合并
【c73cebc75900df125584ff0dbae1ffc1】fix(unidev): 修复 hwproxy 与 hwdiscovery 启动竞态 #298
lishengxiao创建于 7月18日
【c73cebc75900df125584ff0dbae1ffc1】fix(unidev): 修复 hwproxy 与 hwdiscovery 启动竞态 #298
已合并
共 12 个文件变更+176-26
| @@ -1,5 +1,8 @@ | |||
| 1 | # Changelog | 1 | # Changelog |
| 2 | All notable changes to this project will be documented in this file. | 2 | All notable changes to this project will be documented in this file. |
| 3 | +## [1.2.73] - 2026-07-18 | ||
| 4 | +- 修复 unidev 启动竞态:hwproxy 先于 hwdiscovery 启动并发布就绪状态,应用和 hwproxy 就绪后再执行 CSR 全量发现,避免拓扑对象错误注册到 devmon 服务 | ||
| 5 | + | ||
| 3 | ## [1.2.72] - 2026-07-17 | 6 | ## [1.2.72] - 2026-07-17 |
| 4 | - 修复组件编译报错 | 7 | - 修复组件编译报错 |
| 5 | 8 | ||
| @@ -32,9 +32,9 @@ | |||
| 32 | { | 32 | { |
| 33 | "api_version": "v1", | 33 | "api_version": "v1", |
| 34 | "kind": "Service", | 34 | "kind": "Service", |
| 35 | - "type": "discovery_service", | 35 | + "type": "hwproxy_service", |
| 36 | "meta": { | 36 | "meta": { |
| 37 | - "name": "bmc.kepler.hwdiscovery" | 37 | + "name": "bmc.kepler.hwproxy" |
| 38 | }, | 38 | }, |
| 39 | "enabled": true, | 39 | "enabled": true, |
| 40 | "properties": { | 40 | "properties": { |
| @@ -48,9 +48,9 @@ | |||
| 48 | { | 48 | { |
| 49 | "api_version": "v1", | 49 | "api_version": "v1", |
| 50 | "kind": "Service", | 50 | "kind": "Service", |
| 51 | - "type": "hwproxy_service", | 51 | + "type": "discovery_service", |
| 52 | "meta": { | 52 | "meta": { |
| 53 | - "name": "bmc.kepler.hwproxy" | 53 | + "name": "bmc.kepler.hwdiscovery" |
| 54 | }, | 54 | }, |
| 55 | "enabled": true, | 55 | "enabled": true, |
| 56 | "properties": { | 56 | "properties": { |
| @@ -0,0 +1,22 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * openUBMC is licensed under Mulan PSL v2. | ||
| 4 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 5 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 6 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 8 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 9 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 10 | + * See the Mulan PSL v2 for more details. | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +#pragma once | ||
| 14 | + | ||
| 15 | +namespace devmon::service_readiness { | ||
| 16 | + | ||
| 17 | +void set_application_ready(bool ready); | ||
| 18 | +bool is_application_ready(); | ||
| 19 | +void set_hwproxy_ready(bool ready); | ||
| 20 | +bool is_hwproxy_ready(); | ||
| 21 | + | ||
| 22 | +} // namespace devmon::service_readiness | ||
| @@ -13,6 +13,7 @@ common_sources = [ | |||
| 13 | 'src/csr_types.cpp', | 13 | 'src/csr_types.cpp', |
| 14 | 'src/object_group.cpp', | 14 | 'src/object_group.cpp', |
| 15 | 'src/object_group_interface.cpp', | 15 | 'src/object_group_interface.cpp', |
| 16 | + 'src/service_readiness.cpp', | ||
| 16 | 'src/device_driver.cpp', | 17 | 'src/device_driver.cpp', |
| 17 | 'src/device/manager.cpp', | 18 | 'src/device/manager.cpp', |
| 18 | 'src/device/csr.cpp', | 19 | 'src/device/csr.cpp', |
| @@ -0,0 +1,45 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * openUBMC is licensed under Mulan PSL v2. | ||
| 4 | + * You can use this software according to the terms and conditions of the Mulan PSL v2. | ||
| 5 | + * You may obtain a copy of Mulan PSL v2 at: | ||
| 6 | + * http://license.coscl.org.cn/MulanPSL2 | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, | ||
| 8 | + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, | ||
| 9 | + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | ||
| 10 | + * See the Mulan PSL v2 for more details. | ||
| 11 | + */ | ||
| 12 | + | ||
| 13 | +#include <devmon-common/service_readiness.h> | ||
| 14 | + | ||
| 15 | +#include <atomic> | ||
| 16 | + | ||
| 17 | +namespace devmon::service_readiness { | ||
| 18 | +namespace { | ||
| 19 | + | ||
| 20 | +std::atomic<bool> g_application_ready{false}; | ||
| 21 | +std::atomic<bool> g_hwproxy_ready{false}; | ||
| 22 | + | ||
| 23 | +} // namespace | ||
| 24 | + | ||
| 25 | +void set_application_ready(bool ready) | ||
| 26 | +{ | ||
| 27 | + g_application_ready.store(ready, std::memory_order_release); | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +bool is_application_ready() | ||
| 31 | +{ | ||
| 32 | + return g_application_ready.load(std::memory_order_acquire); | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +void set_hwproxy_ready(bool ready) | ||
| 36 | +{ | ||
| 37 | + g_hwproxy_ready.store(ready, std::memory_order_release); | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +bool is_hwproxy_ready() | ||
| 41 | +{ | ||
| 42 | + return g_hwproxy_ready.load(std::memory_order_acquire); | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +} // namespace devmon::service_readiness | ||
| @@ -12,10 +12,9 @@ | |||
| 12 | #ifndef DEVMON_DISCOVERY_SERVICE_H | 12 | #ifndef DEVMON_DISCOVERY_SERVICE_H |
| 13 | #define DEVMON_DISCOVERY_SERVICE_H | 13 | #define DEVMON_DISCOVERY_SERVICE_H |
| 14 | 14 | ||
| 15 | -#include <chrono> | 15 | +#include <atomic> |
| 16 | #include <mc/app/service.h> | 16 | #include <mc/app/service.h> |
| 17 | #include <mc/future.h> | 17 | #include <mc/future.h> |
| 18 | -#include <mc/log.h> | ||
| 19 | #include <mc/reflect.h> | 18 | #include <mc/reflect.h> |
| 20 | #include <optional> | 19 | #include <optional> |
| 21 | 20 | ||
| @@ -42,19 +41,7 @@ public: | |||
| 42 | explicit discovery_service(mc::string name) : mc::app::service(std::move(name)) | 41 | explicit discovery_service(mc::string name) : mc::app::service(std::move(name)) |
| 43 | {} | 42 | {} |
| 44 | 43 | ||
| 45 | - ~discovery_service() override | 44 | + ~discovery_service() override; |
| 46 | - { | ||
| 47 | - if (m_async_task.has_value()) { | ||
| 48 | - try { | ||
| 49 | - auto status = m_async_task->wait_for(std::chrono::seconds(30)); | ||
| 50 | - if (status == mc::future_status::timeout) { | ||
| 51 | - wlog("discovery_service async task timed out during destructor"); | ||
| 52 | - } | ||
| 53 | - } catch (const std::exception& e) { | ||
| 54 | - wlog("exception waiting for async task during destructor: ${error}", ("error", e.what())); | ||
| 55 | - } | ||
| 56 | - } | ||
| 57 | - } | ||
| 58 | 45 | ||
| 59 | private: | 46 | private: |
| 60 | bool on_configure() override; | 47 | bool on_configure() override; |
| @@ -65,6 +52,7 @@ private: | |||
| 65 | hwdiscovery_root_object_ptr m_root_object; | 52 | hwdiscovery_root_object_ptr m_root_object; |
| 66 | kepler_object_group_root_ptr m_object_group_root; | 53 | kepler_object_group_root_ptr m_object_group_root; |
| 67 | std::optional<mc::future<void>> m_async_task; | 54 | std::optional<mc::future<void>> m_async_task; |
| 55 | + std::atomic<bool> m_stop_requested{false}; | ||
| 68 | }; | 56 | }; |
| 69 | 57 | ||
| 70 | } // namespace devmon | 58 | } // namespace devmon |
| @@ -9,18 +9,69 @@ | |||
| 9 | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. | 9 | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. |
| 10 | * See the Mulan PSL v2 for more details. | 10 | * See the Mulan PSL v2 for more details. |
| 11 | */ | 11 | */ |
| 12 | +#include <mc/app/application.h> | ||
| 12 | #include <mc/filesystem.h> | 13 | #include <mc/filesystem.h> |
| 13 | #include <mc/log.h> | 14 | #include <mc/log.h> |
| 14 | #include <mc/runtime.h> | 15 | #include <mc/runtime.h> |
| 15 | 16 | ||
| 17 | +#include <chrono> | ||
| 18 | +#include <thread> | ||
| 19 | + | ||
| 16 | #include <devmon-common/app_schema.h> | 20 | #include <devmon-common/app_schema.h> |
| 17 | #include <devmon-common/device_driver.h> | 21 | #include <devmon-common/device_driver.h> |
| 22 | +#include <devmon-common/service_readiness.h> | ||
| 18 | #include <hwdiscovery/component/csr_config.h> | 23 | #include <hwdiscovery/component/csr_config.h> |
| 19 | #include <hwdiscovery/discovery/discovery.h> | 24 | #include <hwdiscovery/discovery/discovery.h> |
| 20 | #include <hwdiscovery/discovery/kepler_object_group.h> | 25 | #include <hwdiscovery/discovery/kepler_object_group.h> |
| 21 | #include <hwdiscovery/discovery_service.h> | 26 | #include <hwdiscovery/discovery_service.h> |
| 22 | 27 | ||
| 23 | namespace devmon { | 28 | namespace devmon { |
| 29 | +namespace { | ||
| 30 | + | ||
| 31 | +constexpr auto DISCOVERY_DEPENDENCY_RETRY_INTERVAL = std::chrono::milliseconds(50); | ||
| 32 | +constexpr auto DISCOVERY_DEPENDENCY_TIMEOUT = std::chrono::seconds(60); | ||
| 33 | +constexpr const char* HWPROXY_SERVICE_NAME = "bmc.kepler.hwproxy"; | ||
| 34 | + | ||
| 35 | +bool wait_for_discovery_dependencies(mc::app::application* app, const std::atomic<bool>& stop_requested) | ||
| 36 | +{ | ||
| 37 | + const auto deadline = std::chrono::steady_clock::now() + DISCOVERY_DEPENDENCY_TIMEOUT; | ||
| 38 | + nlog("Waiting for application and hwproxy service readiness before discovery"); | ||
| 39 | + | ||
| 40 | + while (!stop_requested.load(std::memory_order_acquire)) { | ||
| 41 | + if (app != nullptr && service_readiness::is_application_ready() && service_readiness::is_hwproxy_ready() && | ||
| 42 | + app->get_service(HWPROXY_SERVICE_NAME)) { | ||
| 43 | + nlog("Application and hwproxy service are ready for discovery"); | ||
| 44 | + return true; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + if (std::chrono::steady_clock::now() >= deadline) { | ||
| 48 | + elog("Timed out waiting for application and hwproxy service readiness; discovery will not start"); | ||
| 49 | + return false; | ||
| 50 | + } | ||
| 51 | + std::this_thread::sleep_for(DISCOVERY_DEPENDENCY_RETRY_INTERVAL); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + ilog("Discovery readiness wait cancelled during service shutdown"); | ||
| 55 | + return false; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +} // namespace | ||
| 59 | + | ||
| 60 | +discovery_service::~discovery_service() | ||
| 61 | +{ | ||
| 62 | + m_stop_requested.store(true, std::memory_order_release); | ||
| 63 | + if (!m_async_task.has_value()) { | ||
| 64 | + return; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + try { | ||
| 68 | + if (m_async_task->wait_for(std::chrono::seconds(30)) == mc::future_status::timeout) { | ||
| 69 | + wlog("discovery_service async task timed out during destructor"); | ||
| 70 | + } | ||
| 71 | + } catch (const std::exception& e) { | ||
| 72 | + wlog("exception waiting for async task during destructor: ${error}", ("error", e.what())); | ||
| 73 | + } | ||
| 74 | +} | ||
| 24 | 75 | ||
| 25 | bool discovery_service::on_configure() | 76 | bool discovery_service::on_configure() |
| 26 | { | 77 | { |
| @@ -33,6 +84,7 @@ bool discovery_service::on_configure() | |||
| 33 | 84 | ||
| 34 | bool discovery_service::on_start() | 85 | bool discovery_service::on_start() |
| 35 | { | 86 | { |
| 87 | + m_stop_requested.store(false, std::memory_order_release); | ||
| 36 | m_root_object = hwdiscovery_root_object::create_hwdiscovery_root_object(this); | 88 | m_root_object = hwdiscovery_root_object::create_hwdiscovery_root_object(this); |
| 37 | m_object_group_root = kepler_object_group_root::create_object(this); | 89 | m_object_group_root = kepler_object_group_root::create_object(this); |
| 38 | ilog("Starting discovery service: ${name}", ("name", name())); | 90 | ilog("Starting discovery service: ${name}", ("name", name())); |
| @@ -40,9 +92,21 @@ bool discovery_service::on_start() | |||
| 40 | auto task_promise = mc::make_promise<void>(); | 92 | auto task_promise = mc::make_promise<void>(); |
| 41 | m_async_task = task_promise.get_future(); | 93 | m_async_task = task_promise.get_future(); |
| 42 | 94 | ||
| 95 | + mc::app::application* app = nullptr; | ||
| 96 | + try { | ||
| 97 | + app = &context().app(); | ||
| 98 | + } catch (const std::exception&) { | ||
| 99 | + // Standalone service tests do not inject a service context. | ||
| 100 | + } | ||
| 101 | + | ||
| 43 | mc::post( | 102 | mc::post( |
| 44 | - [this, task_promise = std::move(task_promise)]() mutable { | 103 | + [this, app, task_promise = std::move(task_promise)]() mutable { |
| 45 | try { | 104 | try { |
| 105 | + if (!wait_for_discovery_dependencies(app, m_stop_requested)) { | ||
| 106 | + task_promise.set_value(); | ||
| 107 | + return; | ||
| 108 | + } | ||
| 109 | + | ||
| 46 | ilog("Starting asynchronous CSR config initialization and discovery for service: " | 110 | ilog("Starting asynchronous CSR config initialization and discovery for service: " |
| 47 | "${name}", | 111 | "${name}", |
| 48 | ("name", name())); | 112 | ("name", name())); |
| @@ -70,6 +134,7 @@ bool discovery_service::on_start() | |||
| 70 | 134 | ||
| 71 | bool discovery_service::on_stop() | 135 | bool discovery_service::on_stop() |
| 72 | { | 136 | { |
| 137 | + m_stop_requested.store(true, std::memory_order_release); | ||
| 73 | if (m_async_task.has_value()) { | 138 | if (m_async_task.has_value()) { |
| 74 | ilog("Waiting for asynchronous tasks to complete before stopping service: ${name}", ("name", name())); | 139 | ilog("Waiting for asynchronous tasks to complete before stopping service: ${name}", ("name", name())); |
| 75 | 140 | ||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include <mc/filesystem.h> | 21 | #include <mc/filesystem.h> |
| 22 | #include <mc/log.h> | 22 | #include <mc/log.h> |
| 23 | 23 | ||
| 24 | +#include <devmon-common/service_readiness.h> | ||
| 25 | + | ||
| 24 | #include <sstream> | 26 | #include <sstream> |
| 25 | 27 | ||
| 26 | namespace devmon { | 28 | namespace devmon { |
| @@ -119,13 +121,16 @@ hwproxy_service::hwproxy_service(mc::string name) : mc::app::service(std::move(n | |||
| 119 | 121 | ||
| 120 | bool hwproxy_service::on_start() | 122 | bool hwproxy_service::on_start() |
| 121 | { | 123 | { |
| 124 | + service_readiness::set_hwproxy_ready(false); | ||
| 122 | m_root_object = hwproxy_root_object::create_hwproxy_root_object(this); | 125 | m_root_object = hwproxy_root_object::create_hwproxy_root_object(this); |
| 126 | + service_readiness::set_hwproxy_ready(true); | ||
| 123 | ilog("hwproxy service started"); | 127 | ilog("hwproxy service started"); |
| 124 | return true; | 128 | return true; |
| 125 | } | 129 | } |
| 126 | 130 | ||
| 127 | bool hwproxy_service::on_stop() | 131 | bool hwproxy_service::on_stop() |
| 128 | { | 132 | { |
| 133 | + service_readiness::set_hwproxy_ready(false); | ||
| 129 | try { | 134 | try { |
| 130 | auto& object_table = get_object_table(); | 135 | auto& object_table = get_object_table(); |
| 131 | if (object_table.find_object(mc::engine::by_path::field == "/bmc/hwproxy")) { | 136 | if (object_table.find_object(mc::engine::by_path::field == "/bmc/hwproxy")) { |
| @@ -12,6 +12,7 @@ hwproxy_test_lib = static_library( | |||
| 12 | hwproxy_dep, | 12 | hwproxy_dep, |
| 13 | common_dep, | 13 | common_dep, |
| 14 | gtest_dep, | 14 | gtest_dep, |
| 15 | + test_utilities_dep, | ||
| 15 | ], | 16 | ], |
| 16 | include_directories: [ | 17 | include_directories: [ |
| 17 | include_directories('../include'), | 18 | include_directories('../include'), |
| @@ -10,15 +10,19 @@ | |||
| 10 | * See the Mulan PSL v2 for more details. | 10 | * See the Mulan PSL v2 for more details. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | +#include <devmon-common/service_readiness.h> | ||
| 13 | #include <gtest/gtest.h> | 14 | #include <gtest/gtest.h> |
| 14 | #include <hwproxy/hwproxy_root_object.h> | 15 | #include <hwproxy/hwproxy_root_object.h> |
| 15 | #include <hwproxy/hwproxy_service.h> | 16 | #include <hwproxy/hwproxy_service.h> |
| 16 | #include <mc/filesystem.h> | 17 | #include <mc/filesystem.h> |
| 18 | +#include <test_utilities/test_base.h> | ||
| 17 | 19 | ||
| 18 | #include <unistd.h> | 20 | #include <unistd.h> |
| 19 | 21 | ||
| 20 | namespace { | 22 | namespace { |
| 21 | 23 | ||
| 24 | +class HwproxyServiceTest : public mc::test::TestWithDbusDaemon {}; | ||
| 25 | + | ||
| 22 | // 测试 hwproxy 服务构造 | 26 | // 测试 hwproxy 服务构造 |
| 23 | TEST(HwproxyService, CanConstruct) | 27 | TEST(HwproxyService, CanConstruct) |
| 24 | { | 28 | { |
| @@ -34,6 +38,19 @@ TEST(HwproxyService, CanInit) | |||
| 34 | EXPECT_TRUE(service.init(args)); | 38 | EXPECT_TRUE(service.init(args)); |
| 35 | } | 39 | } |
| 36 | 40 | ||
| 41 | +TEST_F(HwproxyServiceTest, PublishesReadinessWhileStarted) | ||
| 42 | +{ | ||
| 43 | + devmon::service_readiness::set_hwproxy_ready(false); | ||
| 44 | + auto service = mc::make_shared<devmon::hwproxy_service>("bmc.kepler.hwproxy"); | ||
| 45 | + ASSERT_TRUE(service->init({})); | ||
| 46 | + | ||
| 47 | + ASSERT_TRUE(service->start()); | ||
| 48 | + EXPECT_TRUE(devmon::service_readiness::is_hwproxy_ready()); | ||
| 49 | + | ||
| 50 | + EXPECT_TRUE(service->stop()); | ||
| 51 | + EXPECT_FALSE(devmon::service_readiness::is_hwproxy_ready()); | ||
| 52 | +} | ||
| 53 | + | ||
| 37 | TEST(HwproxyService, OnDumpCreatesSnapshot) | 54 | TEST(HwproxyService, OnDumpCreatesSnapshot) |
| 38 | { | 55 | { |
| 39 | devmon::hwproxy_service service("bmc.kepler.hwproxy.dump"); | 56 | devmon::hwproxy_service service("bmc.kepler.hwproxy.dump"); |
| @@ -55,7 +72,4 @@ TEST(HwproxyService, OnDumpCreatesSnapshot) | |||
| 55 | mc::filesystem::remove_all(test_dir); | 72 | mc::filesystem::remove_all(test_dir); |
| 56 | } | 73 | } |
| 57 | 74 | ||
| 58 | -// 注意:start() 测试需要 DBus 连接,在 CI 环境中可能失败 | ||
| 59 | -// 实际的服务启动和根对象创建功能已在 devmon_tests 中通过集成测试验证 | ||
| 60 | - | ||
| 61 | } // namespace | 75 | } // namespace |
| @@ -2,7 +2,7 @@ | |||
| 2 | "name": "devmon", | 2 | "name": "devmon", |
| 3 | "type": "application", | 3 | "type": "application", |
| 4 | "deployConfig": "", | 4 | "deployConfig": "", |
| 5 | - "version": "1.2.72", | 5 | + "version": "1.2.73", |
| 6 | "license": "", | 6 | "license": "", |
| 7 | "description": "", | 7 | "description": "", |
| 8 | "options": { | 8 | "options": { |
| @@ -10,6 +10,7 @@ | |||
| 10 | * See the Mulan PSL v2 for more details. | 10 | * See the Mulan PSL v2 for more details. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | +#include <devmon-common/service_readiness.h> | ||
| 13 | #include <devmon/devmon.h> | 14 | #include <devmon/devmon.h> |
| 14 | #if DEVMON_ENABLE_UNIDEV | 15 | #if DEVMON_ENABLE_UNIDEV |
| 15 | #include <hwdiscovery/discovery_service.h> | 16 | #include <hwdiscovery/discovery_service.h> |
| @@ -47,10 +48,11 @@ int main(int argc, char** argv) | |||
| 47 | ilog("architecture mode: ${mode}", ("mode", DEVMON_ENABLE_UNIDEV ? "three-layer" : "single")); | 48 | ilog("architecture mode: ${mode}", ("mode", DEVMON_ENABLE_UNIDEV ? "three-layer" : "single")); |
| 48 | 49 | ||
| 49 | mc::app::application app; | 50 | mc::app::application app; |
| 51 | + devmon::service_readiness::set_application_ready(false); | ||
| 50 | app.register_service<devmon::devmon_service>("devmon_service"); | 52 | app.register_service<devmon::devmon_service>("devmon_service"); |
| 51 | #if DEVMON_ENABLE_UNIDEV | 53 | #if DEVMON_ENABLE_UNIDEV |
| 52 | - app.register_service<devmon::discovery_service>("discovery_service"); | ||
| 53 | app.register_service<devmon::hwproxy_service>("hwproxy_service"); | 54 | app.register_service<devmon::hwproxy_service>("hwproxy_service"); |
| 55 | + app.register_service<devmon::discovery_service>("discovery_service"); | ||
| 54 | #endif | 56 | #endif |
| 55 | 57 | ||
| 56 | if (!app.initialize(mc::app::app_options{argc, argv})) { | 58 | if (!app.initialize(mc::app::app_options{argc, argv})) { |
| @@ -61,10 +63,14 @@ int main(int argc, char** argv) | |||
| 61 | elog("start devmon app failed"); | 63 | elog("start devmon app failed"); |
| 62 | return 1; | 64 | return 1; |
| 63 | } | 65 | } |
| 66 | + devmon::service_readiness::set_application_ready(true); | ||
| 64 | 67 | ||
| 65 | ilog("devmon started"); | 68 | ilog("devmon started"); |
| 66 | - return app.exec(); | 69 | + const int exit_code = app.exec(); |
| 70 | + devmon::service_readiness::set_application_ready(false); | ||
| 71 | + return exit_code; | ||
| 67 | } catch (const std::exception& e) { | 72 | } catch (const std::exception& e) { |
| 73 | + devmon::service_readiness::set_application_ready(false); | ||
| 68 | elog("error: ${error}", ("error", e.what())); | 74 | elog("error: ${error}", ("error", e.what())); |
| 69 | return 1; | 75 | return 1; |
| 70 | } | 76 | } |