From 72e4d069dcbc8e771b64c943d2dc519f15f36c48 Mon Sep 17 00:00:00 2001 From: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> Date: Thu, 6 Aug 2026 10:04:03 +0200 Subject: [PATCH] fix(iot-hub-device-update): refresh omnect_1.4.0.patch to fork tip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary Regenerate `omnect_1.4.0.patch` as `git diff 1.4.0..omnect/omnect_1.4.0` at bb060d21 so the patch matches every commit currently on the omnect fork branch. Reason The new hunks come from two places: - omnect/iot-hub-device-update#56 (bb060d21): `sd_notify(EXTEND_TIMEOUT_USEC=…)` from `Connection_Maintenance()` right after it schedules the next authentication attempt, plus a bounded grace on the first `DoWork` tick. The `activating (start)` deadline systemd uses to kill the unit now follows the SDK's retry cadence, so a first-boot with the hub unreachable does not crash-loop the agent to `NRestarts=3` within the default 90s TimeoutStartSec. - omnect/iot-hub-device-update#54 (e2315265, merged earlier): a `DIAGNOSTICS_DEVICENAMES_H` header-guard typo fix in `src/diagnostics_component/diagnostics_devicename/inc/diagnostics_devicename.h`, and the removal of `#define _XOPEN_SOURCE 700` in `src/utils/apiproto_utils/inc/aduc/apiproto.h`. Both had been on the fork branch for two weeks; the patch here had drifted away from the branch's actual state and picks them up on the same regenerate. Signed-off-by: Jan Zachmann 50990105+JanZachmann@users.noreply.github.com --- .../iot-hub-device-update/omnect_1.4.0.patch | 160 +++++++++++++++++- 1 file changed, 156 insertions(+), 4 deletions(-) diff --git a/recipes-azure-iot/iot-hub-device-update/iot-hub-device-update/omnect_1.4.0.patch b/recipes-azure-iot/iot-hub-device-update/iot-hub-device-update/omnect_1.4.0.patch index 569a21e8..a5ecc971 100644 --- a/recipes-azure-iot/iot-hub-device-update/iot-hub-device-update/omnect_1.4.0.patch +++ b/recipes-azure-iot/iot-hub-device-update/iot-hub-device-update/omnect_1.4.0.patch @@ -638,10 +638,18 @@ index 0e52b667..8620349c 100644 target_link_libraries (${target_name} PRIVATE libaducpal) diff --git a/src/communication_managers/iothub_communication_manager/src/iothub_communication_manager.c b/src/communication_managers/iothub_communication_manager/src/iothub_communication_manager.c -index 89a2523c..563feb37 100644 +index 89a2523c..4bf4ef28 100644 --- a/src/communication_managers/iothub_communication_manager/src/iothub_communication_manager.c +++ b/src/communication_managers/iothub_communication_manager/src/iothub_communication_manager.c -@@ -43,6 +43,8 @@ +@@ -23,6 +23,7 @@ + #include + + #include ++#include + + #ifdef ADUC_ALLOW_MQTT + # include +@@ -43,6 +44,8 @@ #include @@ -650,7 +658,7 @@ index 89a2523c..563feb37 100644 /** * @brief A pointer to ADUC_ClientHandle data. This must be initialize by the component that creates the IoT Hub connection. */ -@@ -68,6 +70,11 @@ static IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK g_device_twin_callback = NULL; +@@ -68,6 +71,11 @@ static IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK g_device_twin_callback = NULL; */ static bool g_iothub_client_initialized = false; @@ -662,7 +670,7 @@ index 89a2523c..563feb37 100644 /** * @brief An additional data context used the caller. */ -@@ -337,6 +344,11 @@ void IoTHub_CommunicationManager_ConnectionStatus_Callback( +@@ -337,6 +345,11 @@ void IoTHub_CommunicationManager_ConnectionStatus_Callback( case IOTHUB_CLIENT_CONNECTION_AUTHENTICATED: g_last_authenticated_time = now_time; g_authentication_retries = 0; @@ -674,6 +682,90 @@ index 89a2523c..563feb37 100644 break; case IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED: if (IoTHub_CommunicationManager_CategorizeUnauthenticated(status_reason) +@@ -944,6 +957,57 @@ done: + ADUC_ConnectionInfo_DeAlloc(&info); + } + ++// Margin over the just-scheduled retry delay: sized to outlast the retry ++// itself plus the SDK's TCP connect (~127s at kernel defaults) plus one ++// DoWork tick, so systemd never SIGTERMs between two consecutive extends. ++#define EXTEND_MARGIN_SECS 60 ++ ++// Bounded grace for the very first connect attempt, before any retry has ++// been scheduled. Aligned with the SDK's NO_NETWORK back-off so it outlasts ++// a full kernel SYN-retry cycle (~127s). ++#define FIRST_CONNECT_GRACE_SECS TIME_SPAN_FIVE_MINUTES_IN_SECONDS ++ ++/** ++ * @brief Build the `EXTEND_TIMEOUT_USEC=` payload for `sd_notify`. ++ * ++ * @param seconds Grace to request, in seconds. ++ * @param buf Destination buffer for the payload string. ++ * @param buflen Size of @p buf. ++ * @return true if @p buf was filled and should be sent, false when the ++ * input is non-positive or the buffer is unusable. ++ */ ++bool format_extend_timeout_message(time_t seconds, char* buf, size_t buflen) ++{ ++ if (seconds <= 0 || buf == NULL || buflen == 0) ++ { ++ return false; ++ } ++ (void)snprintf( ++ buf, buflen, "EXTEND_TIMEOUT_USEC=%llu", (unsigned long long)seconds * 1000000ULL); ++ return true; ++} ++ ++/** ++ * @brief Push systemd's current-state timeout deadline out by @p seconds. ++ * ++ * Called while the unit is in `activating (start)` so the SDK's own retry ++ * cadence drives when systemd kills the process. After READY=1 has ended ++ * the start it becomes a no-op. Non-fatal on failure; a missing ++ * NOTIFY_SOCKET is a silent no-op too. ++ */ ++static void notify_extend_start_timeout(time_t seconds) ++{ ++ char msg[64]; ++ if (!format_extend_timeout_message(seconds, msg, sizeof(msg))) ++ { ++ return; ++ } ++ if (sd_notify(0, msg) < 0) ++ { ++ Log_Debug("sd_notify(%s) failed: errno=%d", msg, errno); ++ } ++} ++ + /** + * @brief Performs an authentication to the IoTHub as needed, with exponential back-off retry logics. + * +@@ -1038,6 +1102,10 @@ static void Connection_Maintenance() + ADUC_RETRY_DEFAULT_MAX_JITTER_PERCENT); + + g_next_authentication_attempt_time = (nextRetryTime); ++ // Move systemd's deadline in step with the retry we just scheduled ++ // so the SDK's own back-off (e.g. the 5-minute NO_NETWORK delay) ++ // can run its full length. ++ notify_extend_start_timeout(nextRetryTime - now_time + EXTEND_MARGIN_SECS); + Log_Info( + "The connection is currently broken. Will try to authenticate in %d seconds.", nextRetryTime - now_time); + return; +@@ -1058,6 +1126,14 @@ static void Connection_Maintenance() + void IoTHub_CommunicationManager_DoWork(void* user_context) + { + UNREFERENCED_PARAMETER(user_context); ++ if (g_last_authentication_attempt_time == 0) ++ { ++ // First DoWork tick since agent start: no retry has been scheduled ++ // yet, so grant a bounded grace to outlast the initial hub ++ // round-trip. Every later retry extends the deadline again from ++ // Connection_Maintenance(). ++ notify_extend_start_timeout(FIRST_CONNECT_GRACE_SECS); ++ } + Connection_Maintenance(); + ClientHandle_DoWork(*g_aduc_client_handle_address); + } diff --git a/src/communication_managers/iothub_communication_manager/tests/CMakeLists.txt b/src/communication_managers/iothub_communication_manager/tests/CMakeLists.txt index dbd6d5b5..f0d96f74 100644 --- a/src/communication_managers/iothub_communication_manager/tests/CMakeLists.txt @@ -704,6 +796,54 @@ index dbd6d5b5..f0d96f74 100644 target_compile_definitions (${PROJECT_NAME} PRIVATE ADUC_CONF_FILE_PATH="/etc/adu/du-config.json") include (CTest) +diff --git a/src/communication_managers/iothub_communication_manager/tests/iothub_communication_manager_ut.cpp b/src/communication_managers/iothub_communication_manager/tests/iothub_communication_manager_ut.cpp +index d51d2906..6a36d334 100644 +--- a/src/communication_managers/iothub_communication_manager/tests/iothub_communication_manager_ut.cpp ++++ b/src/communication_managers/iothub_communication_manager/tests/iothub_communication_manager_ut.cpp +@@ -1274,3 +1274,24 @@ TEST_CASE("ADO 38069154: unrecognized reason classifies as Unknown (conservative + CHECK(cls != ADUC_ConnReason_Credential); + CHECK(cls != ADUC_ConnReason_DeviceDisabled); + } ++ ++// ++// Tests for format_extend_timeout_message: the pure formatter that backs the ++// sd_notify(EXTEND_TIMEOUT_USEC=...) path in Connection_Maintenance(). ++// ++ ++extern "C" bool format_extend_timeout_message(time_t seconds, char* buf, size_t buflen); ++ ++TEST_CASE("format_extend_timeout_message formats seconds as microseconds") ++{ ++ char buf[64] = { 0 }; ++ CHECK(format_extend_timeout_message(300, buf, sizeof(buf)) == true); ++ CHECK(strcmp(buf, "EXTEND_TIMEOUT_USEC=300000000") == 0); ++} ++ ++TEST_CASE("format_extend_timeout_message returns false for non-positive input") ++{ ++ char buf[64] = { 0 }; ++ CHECK(format_extend_timeout_message(0, buf, sizeof(buf)) == false); ++ CHECK(format_extend_timeout_message(-1, buf, sizeof(buf)) == false); ++} +diff --git a/src/diagnostics_component/diagnostics_devicename/inc/diagnostics_devicename.h b/src/diagnostics_component/diagnostics_devicename/inc/diagnostics_devicename.h +index e5affb15..a5614cdb 100644 +--- a/src/diagnostics_component/diagnostics_devicename/inc/diagnostics_devicename.h ++++ b/src/diagnostics_component/diagnostics_devicename/inc/diagnostics_devicename.h +@@ -6,7 +6,7 @@ + * Licensed under the MIT License. + */ + #ifndef DIAGNOSTICS_DEVICENAMES_H +-# define DIAGNOSTICS_DEVICENAMES_UTILS_H ++# define DIAGNOSTICS_DEVICENAMES_H + + # include + # include +@@ -36,4 +36,4 @@ void DiagnosticsComponent_DestroyDeviceName(void); + + EXTERN_C_END + +-#endif // DIAGNOSTICS_DEVICENAMES_UTILS_H ++#endif // DIAGNOSTICS_DEVICENAMES_H diff --git a/src/diagnostics_component/diagnostics_workflow/CMakeLists.txt b/src/diagnostics_component/diagnostics_workflow/CMakeLists.txt index dc064d3b..15c516fc 100644 --- a/src/diagnostics_component/diagnostics_workflow/CMakeLists.txt @@ -1956,6 +2096,18 @@ index b1c9ee0c..057a483a 100644 { Log_Error("statvfs failed, error: %d", errno); return nullptr; +diff --git a/src/utils/apiproto_utils/inc/aduc/apiproto.h b/src/utils/apiproto_utils/inc/aduc/apiproto.h +index 5e1b6eec..3fc2a9e9 100644 +--- a/src/utils/apiproto_utils/inc/aduc/apiproto.h ++++ b/src/utils/apiproto_utils/inc/aduc/apiproto.h +@@ -11,7 +11,6 @@ + + #include "aduc/c_utils.h" + #include +-#define _XOPEN_SOURCE 700 + #include + #include + diff --git a/src/utils/apiproto_utils/src/apiproto.c b/src/utils/apiproto_utils/src/apiproto.c index 07ef0759..bdf9dd88 100644 --- a/src/utils/apiproto_utils/src/apiproto.c