Skip to content

filed: Enable sleep suppression for client-initiated jobs - #2701

Open
pstorz wants to merge 28 commits into
bareos:masterfrom
pstorz:dev/pstorz/master/client-initiated-backup-fixes
Open

pstorz wants to merge 28 commits into
bareos:masterfrom
pstorz:dev/pstorz/master/client-initiated-backup-fixes

Conversation

@pstorz

@pstorz pstorz commented Jun 19, 2026

Copy link
Copy Markdown
Member

For client-initiated director sessions in filed, start sleep suppression when processing backup or restore commands, while keeping verify unchanged.

Windows support existed before, but was not being called by client-initiated connects.
This PR now also adds Linux and MacOS so that also sleeping is supporessed there while jobs are running.

Thank you for contributing to the Bareos Project!

Please check

  • Short description and the purpose of this PR is present above this paragraph
  • Your name is present in the AUTHORS file (optional)

If you have any questions or problems, please give a comment in the PR.

Helpful documentation and best practices

Checklist for the reviewer of the PR (will be processed by the Bareos team)

Make sure you check/merge the PR using devtools/pr-tool to have some simple automated checks run and a proper changelog record added.

General
  • Is the PR title usable as CHANGELOG entry?
  • Purpose of the PR is understood
  • Commit descriptions are understandable and well formatted
  • Required backport PRs have been created
  • If a release should wait for this PR to be finished, set that release's milestone.
Source code quality
  • Source code changes are understandable
  • Variable and function names are meaningful
  • Code comments are correct (logically and spelling)
  • Required documentation changes are present and part of the PR
Tests
  • Decision taken that a test is required (if not, then remove this paragraph)
  • The choice of the type of test (unit test or systemtest) is reasonable
  • Testname matches exactly what is being tested
  • On a fail, output of the test leads quickly to the origin of the fault

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds cross-platform sleep inhibition during backup and restore commands and introduces client-initiated-only daemon mode for outbound-only Director connections. Build configuration, packaging dependencies, termination handling, and system tests are updated.

Changes

Director command handling and client-initiated mode

Layer / File(s) Summary
Sleep inhibition build configuration
core/src/filed/CMakeLists.txt, core/cmake/BareosCheckIncludes.cmake, core/platforms/packaging/*, debian/control*
Adds the sleep-inhibition option, validates Linux systemd headers, wires platform sources and libraries, and adds systemd development build dependencies.
Sleep inhibition API and platform implementations
core/src/filed/os_suspension.*
Defines shared sleep-prevention state and dispatch functions, with Windows, Linux systemd, and Darwin IOKit implementations.
Command-scoped sleep inhibition
core/src/filed/dir_cmd.cc
Activates sleep prevention for BackupCmd and RestoreCmd, deactivates it during cleanup, and removes connection-time activation.
Client-initiated-only startup and validation
core/src/filed/filed.cc, systemtests/tests/client-initiated/testrunner
Detects outbound-only configurations, skips socket-server startup, handles termination through a pipe, and verifies that no file-daemon listener is available.

Estimated code review effort: 4 (Complex) | ~50 minutes

Sequence Diagram(s)

sequenceDiagram
  participant filed
  participant Director
  participant OS
  filed->>filed: Receive Director command
  filed->>filed: Check for BackupCmd or RestoreCmd
  filed->>OS: ActivateSleepPrevention()
  Director->>filed: Execute backup or restore
  filed->>OS: DeactivateSleepPrevention()
Loading

Suggested reviewers: sebsura

Poem

🐰 Backup hops, the daemon keeps watch,
Sleep stays away while commands are in clutch.
Outbound paths bloom, no listener sings,
Systemd and IOKit guard sleepy things.
The rabbit approves with a moonlit cheer! 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: enabling sleep suppression for client-initiated filed jobs.
Description check ✅ Passed The description includes the purpose, context, and the repository template sections, so it is sufficiently complete.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
core/src/filed/dir_cmd.cc (1)

249-251: 💤 Low value

Consider using kIOPMAssertionTypePreventSystemSleep for consistency with Linux/Windows.

The current implementation uses kIOPMAssertionTypePreventUserIdleSystemSleep, which prevents idle sleep but allows sleep from lid close. Linux's "block" mode and Windows's ES_SYSTEM_REQUIRED prevent all sleep including lid-close initiated sleep.

If a user closes their MacBook lid during a backup, the system may still sleep and interrupt the operation. Consider using kIOPMAssertionTypePreventSystemSleep if you want consistent behavior across platforms.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/filed/dir_cmd.cc` around lines 249 - 251, The
IOPMAssertionCreateWithName call in the file is using
kIOPMAssertionTypePreventUserIdleSystemSleep which only prevents idle sleep but
allows sleep from user actions like closing the lid. To ensure consistent
behavior with Linux and Windows implementations that prevent all sleep states,
replace kIOPMAssertionTypePreventUserIdleSystemSleep with
kIOPMAssertionTypePreventSystemSleep as the first parameter in the
IOPMAssertionCreateWithName call. This will ensure that backup or restore
operations are not interrupted even if the user closes the MacBook lid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@core/src/filed/dir_cmd.cc`:
- Around line 249-251: The IOPMAssertionCreateWithName call in the file is using
kIOPMAssertionTypePreventUserIdleSystemSleep which only prevents idle sleep but
allows sleep from user actions like closing the lid. To ensure consistent
behavior with Linux and Windows implementations that prevent all sleep states,
replace kIOPMAssertionTypePreventUserIdleSystemSleep with
kIOPMAssertionTypePreventSystemSleep as the first parameter in the
IOPMAssertionCreateWithName call. This will ensure that backup or restore
operations are not interrupted even if the user closes the MacBook lid.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fd69c867-55f3-4436-9a14-f18047147aad

📥 Commits

Reviewing files that changed from the base of the PR and between ff8a9bb and 4119060.

📒 Files selected for processing (2)
  • core/src/filed/CMakeLists.txt
  • core/src/filed/dir_cmd.cc

@sduehr

sduehr commented Jun 22, 2026

Copy link
Copy Markdown
Member

On Linux inhibiting suspend only when a jobs runs works now.
But on Windows it inhibits suspend already when bareos-fd is running.

@sebsura
sebsura marked this pull request as draft June 23, 2026 10:20
@sduehr

sduehr commented Jun 24, 2026

Copy link
Copy Markdown
Member

With the last change it now works as expected also on Windows.

@arogge
arogge marked this pull request as ready for review July 7, 2026 10:28
@arogge
arogge requested a review from sebsura July 7, 2026 10:29
Comment thread core/src/filed/CMakeLists.txt Outdated
include(BareosWindowsResource)
include(CheckIncludeFiles)

option(fd-client-sleep-inhibition

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

every other option is UPPER_SNAKE_CASE, why was kebab case chosen here ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to FD_CLIENT_SLEEP_INHIBITION

Comment thread core/src/filed/CMakeLists.txt Outdated
endif()
set(_previous_required_includes "${CMAKE_REQUIRED_INCLUDES}")
set(CMAKE_REQUIRED_INCLUDES ${SYSTEMD_INCLUDE_DIRS})
check_include_files("systemd/sd-bus.h" HAVE_SYSTEMD_SD_BUS_H)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably belongs in BareosCheckIncludes.cmake

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved to BareosCheckIncludes.cmake

Comment thread core/src/filed/CMakeLists.txt Outdated
Comment on lines +92 to +94
target_compile_definitions(fd_objects_common
PRIVATE HAVE_FD_CLIENT_SLEEP_INHIBITION=1
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we not add this to config.h instead ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is only relevant for the fd.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is only relevant for the FD. Renamed to FILED_CLIENT_SLEEP_INHIBITION

endif()
if(HAVE_DARWIN_OS)
target_link_libraries(fd_objects_common PRIVATE "-framework IOKit")
endif()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this even without fd-client-sleep-inhibition ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, changed to HAVE_DARWIN_OS AND FD_CLIENT_SLEEP_INHIBITION

Comment thread core/src/filed/CMakeLists.txt Outdated
else()
target_link_libraries(fd_objects_common PRIVATE systemd)
endif()
endif()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not just part of the upper if ? I do not get why this pr has so many

if (x & a)
if (x & b)
if (x & c)

instead of

if (x)
  if (a)
  if (b)
  if (c)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, good point, was refactored.

Comment thread core/src/filed/dir_cmd.cc Outdated
Comment on lines +542 to +563
[[maybe_unused]] const bool is_backup_or_restore_command
= (to_execute->func == BackupCmd || to_execute->func == RestoreCmd);

#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_WIN32)
if (!sleep_prevention_active && is_backup_or_restore_command) {
PreventOsSuspensions();
sleep_prevention_active = true;
}
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_LINUX_OS) \
&& defined(HAVE_SYSTEMD)
if (is_backup_or_restore_command) {
ActivateLinuxSleepInhibition(jcr, linux_sleep_inhibitor_fd,
linux_sleep_inhibit_warning_logged);
}
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_DARWIN_OS)
if (is_backup_or_restore_command) {
ActivateDarwinSleepInhibition(jcr, darwin_sleep_assertion_id,
darwin_sleep_inhibit_warning_logged);
}
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does only windows care whether sleep is already prevented ?

Why is this not just

#if HAVE_FD_CLIENT_SLEEP_INHIBITION
if (is_backup_or_restore_command) {
  PreventOsSuspensions();
}
#endif

And simply define PreventOsSuspension() depending on the target. We should probably just move everything in filed/os_suspension.h + an impl file per platform.

@pstorz pstorz Jul 20, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, os_suspension.h and os_suspension_{linux,darwin,win32}.cc were added.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, now all OS check for the current state in the corresponding files.

Comment thread core/src/filed/dir_cmd.cc Outdated
Comment on lines +612 to +621
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_WIN32)
AllowOsSuspensions();
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_LINUX_OS) \
&& defined(HAVE_SYSTEMD)
DeactivateLinuxSleepInhibition(linux_sleep_inhibitor_fd);
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_DARWIN_OS)
DeactivateDarwinSleepInhibition(darwin_sleep_assertion_id);
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This should just be

#if ...
  AllowOsSuspensions();
#endif

Comment thread core/src/filed/filed.cc
// Without a listening socket server we still need to keep the daemon process
// alive so client-initiated connection threads can run.
for (;;) { Bmicrosleep(30, 0); }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has to be a better way to do this. What condition are we actually waiting for ? If we know that, we can actually make the code wait on that condition (e.g. via a condition_variable, an atomic_flag, ....).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Was changed to condition variable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still a big loop. Where is the condition variable that you talked about ?

Comment thread core/src/filed/dir_cmd.cc Outdated
Comment on lines +501 to +512
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_WIN32)
bool sleep_prevention_active = false;
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_LINUX_OS) \
&& defined(HAVE_SYSTEMD)
int linux_sleep_inhibitor_fd = -1;
bool linux_sleep_inhibit_warning_logged = false;
#endif
#if defined(HAVE_FD_CLIENT_SLEEP_INHIBITION) && defined(HAVE_DARWIN_OS)
IOPMAssertionID darwin_sleep_assertion_id = kIOPMNullAssertionID;
bool darwin_sleep_inhibit_warning_logged = false;
#endif

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the sleep prevention needs some kind of state, then we should have one SleepPrevention struct or so (with one implementation per os) instead of this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was addressed in the files mentioned above.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
core/src/filed/os_suspension_win32.cc (1)

37-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Check the activation flag before deactivating sleep prevention.

To be consistent with the Linux and Darwin implementations—and to prevent invoking AllowOsSuspensions() unnecessarily when sleep prevention was never activated (such as during a status command)—consider verifying the windows_active flag first.

♻️ Proposed refactor
 void DeactivateWindowsSleepPrevention(SleepPrevention& sleep_prevention)
 {
-  AllowOsSuspensions();
-  sleep_prevention.windows_active = false;
+  if (sleep_prevention.windows_active) {
+    AllowOsSuspensions();
+    sleep_prevention.windows_active = false;
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/src/filed/os_suspension_win32.cc` around lines 37 - 41, Update
DeactivateWindowsSleepPrevention to check sleep_prevention.windows_active before
calling AllowOsSuspensions(). Only perform the OS deactivation and reset the
flag when prevention is currently active; leave the no-op path unchanged for
inactive state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@core/src/filed/os_suspension_win32.cc`:
- Around line 37-41: Update DeactivateWindowsSleepPrevention to check
sleep_prevention.windows_active before calling AllowOsSuspensions(). Only
perform the OS deactivation and reset the flag when prevention is currently
active; leave the no-op path unchanged for inactive state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e2033f89-f204-4de9-8151-448e2a8ce1bc

📥 Commits

Reviewing files that changed from the base of the PR and between cd9d66b and fe1dd8b.

📒 Files selected for processing (9)
  • core/cmake/BareosCheckIncludes.cmake
  • core/src/filed/CMakeLists.txt
  • core/src/filed/dir_cmd.cc
  • core/src/filed/filed.cc
  • core/src/filed/os_suspension.cc
  • core/src/filed/os_suspension.h
  • core/src/filed/os_suspension_darwin.cc
  • core/src/filed/os_suspension_linux.cc
  • core/src/filed/os_suspension_win32.cc
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/src/filed/filed.cc

@pstorz
pstorz force-pushed the dev/pstorz/master/client-initiated-backup-fixes branch from fe1dd8b to b92f4c6 Compare July 20, 2026 13:21
@pstorz
pstorz requested a review from sebsura July 20, 2026 14:31
@arogge arogge added the onhold label Jul 23, 2026

@sebsura sebsura left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are merge conflicts

Comment thread core/src/filed/CMakeLists.txt Outdated
Comment thread core/src/filed/os_suspension.h Outdated
Comment thread core/src/filed/filed.cc
// Without a listening socket server we still need to keep the daemon process
// alive so client-initiated connection threads can run.
for (;;) { Bmicrosleep(30, 0); }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still a big loop. Where is the condition variable that you talked about ?

@arogge arogge assigned pstorz and unassigned sduehr Aug 31, 2026
For client-initiated director sessions in filed, start Windows
sleep suppression when processing backup or restore commands,
while keeping verify unchanged.

This uses the existing end-of-session AllowOsSuspensions()
cleanup and preserves non-Windows behavior.
Add Linux systemd-logind sleep inhibition for filed backup and
restore command processing by acquiring an inhibitor lock and
releasing it at session end. If inhibition cannot be acquired,
continue and log a warning once per session.

Apply sleep inhibition behavior to all director connection paths
(not only client-initiated sessions) and simplify the command
processing API accordingly.

Also link filed with libsystemd when HAVE_SYSTEMD is enabled.
Implement macOS sleep inhibition in filed using IOKit power
assertions and apply the same backup/restore trigger behavior as
other platforms. Keep the assertion active for the session and
release it on teardown.

If creating the assertion fails, continue and log a warning once
per session. Also link filed with IOKit on Darwin.
When no Director allows inbound client connections, skip opening
the filed listener socket and keep the daemon alive for outbound
client-initiated sessions.

Update the client-initiated systemtest to assert that the FD port
is not listening in this mode.
Switch filed from kIOPMAssertionTypePreventUserIdleSystemSleep
to kIOPMAssertionTypePreventSystemSleep so backup and restore
operations keep the system awake under broader sleep triggers.
Use Qmsg for Linux and macOS sleep inhibition warnings so they
are queued and emitted safely via normal job message handling,
without interfering with command parsing.
Only compile Linux sleep inhibition code when <systemd/sd-bus.h> is

available, even if HAVE_SYSTEMD is set. This fixes builds where

systemd is partially detected without development headers.

Also always apply SYSTEMD include dirs and cflags for filed objects

when HAVE_SYSTEMD is enabled, independent of the link-library

fallback branch.
Mark is_backup_or_restore_command as maybe_unused with attribute

placement compatible with current compiler warning settings so

warning-as-error builds succeed when backend-specific inhibition

code is compiled out.
Make client sleep inhibition enabled by default and configurable only

via explicit manual disable.

On Linux, CMake now fails when systemd support or sd-bus headers

are missing while fd-client-sleep-inhibition is enabled.

Add packaging build dependencies for systemd development headers in

Debian and pkg-config(systemd) in RPM specs.
Log sleep inhibition fallback messages with M_INFO instead of

M_WARNING so jobs do not switch to 'OK -- with warnings' when

running in environments where inhibition is unavailable.
Remove the unconditional PreventOsSuspensions() call from Director

connection setup so Windows sleep inhibition only starts when a

backup or restore command is actually processed.
@pstorz pstorz removed the onhold label Sep 7, 2026
@pstorz
pstorz force-pushed the dev/pstorz/master/client-initiated-backup-fixes branch from 7062b03 to 6738dfc Compare September 7, 2026 12:09
@pstorz
pstorz requested a review from sebsura September 7, 2026 15:12
Client-initiated-only mode no longer waits with a pure sleep loop.
Instead, it installs a signal handler that writes a byte to a dedicated
self-pipe, and WaitUntilTerminated() blocks on the pipe read end.

This keeps the signal-handler path async-signal-safe by avoiding
mutex/condition_variable operations in signal context. The process then
continues shutdown in normal flow by calling TerminateFiled() after
wakeup.

When the pipe setup fails, the code falls back to the existing
TerminateFiled signal handler behavior. The termination pipe file
descriptors are closed during shutdown cleanup.
Replace the client-initiated Windows polling loop with a native event.
Explain the self-pipe versus event strategy for signal-safe shutdown.
@pstorz
pstorz force-pushed the dev/pstorz/master/client-initiated-backup-fixes branch from 6738dfc to 13ffefc Compare September 7, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants