Skip to content

upssched: rewrite WIN32 timer daemon spawning code path - #3549

Open
jimklimov wants to merge 2 commits into
networkupstools:masterfrom
jimklimov:issue-3525-upssched
Open

upssched: rewrite WIN32 timer daemon spawning code path#3549
jimklimov wants to merge 2 commits into
networkupstools:masterfrom
jimklimov:issue-3525-upssched

Conversation

@jimklimov

Copy link
Copy Markdown
Member

Expected to help with issue #3525, code proposed by Claude Sonnet and @alexdruqn-cpu in that discussion.

Original description from #3525 (comment) follows:

Summary of All Fixes to upssched.c (Win32)

1. Process-cascade fix (start_daemon() / main() / conf_arg() / checkconf())

  • Root cause: CreateProcess() spawned an unmarked clone of the executable, which inherited UPSNAME/NOTIFYTYPE and re-ran the full CLI path (re-parsing config, re-calling sendcmd()), combined with a racy, unconditional lock-file deletion — causing a runaway spawn cascade instead of one client + one daemon.
  • Fix:
    • Added a hidden marker (WIN32_DAEMON_MARKER) and flag (is_win32_timer_daemon) so a spawned process is explicitly told "you are the daemon," intercepted at the top of main(), bypassing normal CLI/option parsing.
    • conf_arg() now also gates on this flag (same as list_timers) to parse global directives but skip AT-line actions.
    • start_daemon() (Win32 branch) rewritten: clears UPSNAME/NOTIFYTYPE/NOTIFYMSG before spawning, passes a readiness-event HANDLE to the child, waits on it (CreateEvent/WaitForSingleObject) instead of becoming the daemon itself, then returns — mirroring the non-WIN32 parent branch.
    • Extracted the daemon's server loop into a new win32_run_timer_daemon(), entered only by the marked child; it calls SetEvent() once its named pipe is listening.
    • Fixed a handle leak: pinfo.hProcess/hThread are now closed after CreateProcess().

2. Overlapped-read fix (sendcmd(), Win32 branch) — explains "read confirmation got []"

  • Root cause: while (ReadFile(...)) used the call's return value as the loop condition. For an overlapped pipe handle, FALSE + ERROR_IO_PENDING is the normal pending state, not failure — so the loop body (which waited on the event and parsed the reply) was almost never entered, leaving buf empty.
  • Also found: the continue/break inside that loop were meant to retry/give up on the outer for (i < MAX_TRIES) loop but only affected the inner (dead) loop — and did so after CloseHandle(pipefd), risking a read on an already-closed handle. GetOverlappedResult() was never called, and both pipefd (on success) and read_overlapped.hEvent (always) leaked.
  • Fix: correctly distinguish real errors from ERROR_IO_PENDING, call GetOverlappedResult() to get the actual byte count and NUL-terminate properly, replace the nested loop with a win32_outer_action flag so break/continue sit directly in the outer loop, and close both handles exactly once on every exit path.

Not a bug (clarified, no code change):

  • FILE_FLAG_OVERLAPPED + PIPE_WAIT in CreateNamedPipe() — correct, documented combination; PIPE_WAIT only affects non-overlapped calls, which this code never makes.
  • The apparent "extra newline" in [OK\n] in the logs — literal \n byte inside the real 3-byte "OK\n" payload, just printed unescaped by upsdebugx.

Both patches were verified for brace/paren balance and cross-checked against common.h/wincompat.h/upssched.h (confirmed TYPE_FD == HANDLE, <windows.h> availability, etc.), but not compiled — no Win32 cross-compiler available in this environment, so a real build/test on your side is still needed.

…de path [networkupstools#3525]

Co-authored-by: @alexdruqn-cpu
Co-authored-by: Claude Sonnet 4.6
Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
@jimklimov jimklimov added this to the 2.8.6 milestone Jul 27, 2026
@jimklimov jimklimov added bug service/daemon start/stop General subject for starting and stopping NUT daemons (drivers, server, monitor); also BG/FG/Debug Windows-not-on-par-with-POSIX Aspect of Windows builds known to be dysfunctional compared to POSIX builds; fix needed to be on par upssched Questions and issues about upssched (timer helper for upsmon) Shutdowns and overrides and battery level triggers Issues and PRs about system shutdown, especially if battery charge/runtime remaining is involved impacts-release-2.8.5 Issues reported against NUT release 2.8.5 (maybe vanilla or with minor packaging tweaks) AI For good or bad, machine tools are upon us. Humans are still the responsible ones. labels Jul 27, 2026
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown

A ZIP file with standard source tarball and another tarball with pre-built docs for commit 57e63a2 is temporarily available: NUT-tarballs-PR-3549.zip.

@AppVeyorBot

Copy link
Copy Markdown

Build nut 2.8.5.4992-master completed (commit 8a19fd3f01 by @jimklimov)

@AppVeyorBot

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI For good or bad, machine tools are upon us. Humans are still the responsible ones. bug impacts-release-2.8.5 Issues reported against NUT release 2.8.5 (maybe vanilla or with minor packaging tweaks) service/daemon start/stop General subject for starting and stopping NUT daemons (drivers, server, monitor); also BG/FG/Debug Shutdowns and overrides and battery level triggers Issues and PRs about system shutdown, especially if battery charge/runtime remaining is involved upssched Questions and issues about upssched (timer helper for upsmon) Windows-not-on-par-with-POSIX Aspect of Windows builds known to be dysfunctional compared to POSIX builds; fix needed to be on par

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants