ZBX-27897 - fix validation evidence ==================================== Server built from git tag 7.0.27 (./configure --enable-server --with-postgresql --with-openssl --with-libevent --with-libcurl --with-libpcre2), run against a real PostgreSQL backend. Temporary debug logging (LOG_LEVEL_WARNING, "ORPHANDBG ...") was added at the two timer_revision=0 reset sites and at timer (re)creation (dc_update_function_timer / dc_update_trigger_timer) to obtain ground truth. The debug logging is NOT part of the submitted patch. Method (deterministic, per-trial restart) ------------------------------------------ Each trial: 1. restart the server (clean ZBX_DBSYNC_INIT -> the time-based timer is created once); 2. disable the referenced item -> trigger becomes non-functional; within one timer period the timer pops while non-functional and timer_revision is reset to 0 (logged: validate-reset / validate-reset-tr); 3. re-enable the item (this is the next configuration-changing sync); 4. check whether the timer is recreated afterwards (logged: upd-fn-timer / upd-tr-timer occurring after the reset line). reset=1 confirms the orphan was actually induced in that trial (identical in both arms). recreated=1 means the timer was rescheduled after re-enable -> trigger recovers. recreated=0 means the timer stayed orphaned -> trigger frozen (the bug). Restart-per-trial is used so every trial induces exactly one fresh orphan; the only variable between the two arms is the server binary. Test objects ------------ Function-timer path: item 900011 (trapper) + trigger 900101 = nodata(/host/900011,30s). Trigger-timer path: trigger 900102 = "time()>=0 and {900202}>=0", where {900202} = last() on item 900011 (time() forces a trigger-level timer, ZBX_TRIGGER_TIMER_TRIGGER; the item reference makes the trigger non-functional when the item is disabled). Results ------- Function-timer path (nodata): VANILLA trials 1..10: reset=1 recreated=0 => STUCK (recovered=0 stuck=10) PATCHED trials 1..10: reset=1 recreated=1 => RECOVERED (recovered=10 stuck=0) Trigger-timer path (time()): VANILLA trials 1..10: reset=1 recreated=0 => STUCK (recovered=0 stuck=10) PATCHED trials 1..10: reset=1 recreated=1 => RECOVERED (recovered=10 stuck=0) Summary ------- vanilla 7.0.27 : 0/20 recovered (20/20 stuck) - reproduces the bug on both paths patched : 20/20 recovered (0/20 stuck) - timer recreated every time In every one of the 40 trials the orphan reset was induced (reset=1), so the conditions were identical across arms; vanilla never recreated the timer (trigger frozen), the patched build recreated it every time (trigger resumes scheduled recalculation). Single-step instrumented contrast (illustrative, function path) --------------------------------------------------------------- vanilla : upd-fn-timer (INIT) -> validate-reset (item disabled) -> [item enabled] -> NO upd-fn-timer => trigger stays val=0 through a silent (no-data) probe patched : upd-fn-timer (INIT) -> validate-reset (item disabled) -> [item enabled] -> upd-fn-timer (drain re-fed the function) => trigger -> PROBLEM on the silent probe (timer alive again) Build ----- dbconfig.c / dbconfig.h compile with -Wall -Wextra and no new warnings; the patch applies cleanly to the 7.0.27 tag.