Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe 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. ChangesDirector command handling and client-initiated mode
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()
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
core/src/filed/dir_cmd.cc (1)
249-251: 💤 Low valueConsider using
kIOPMAssertionTypePreventSystemSleepfor 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'sES_SYSTEM_REQUIREDprevent 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
kIOPMAssertionTypePreventSystemSleepif 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
📒 Files selected for processing (2)
core/src/filed/CMakeLists.txtcore/src/filed/dir_cmd.cc
|
On Linux inhibiting suspend only when a jobs runs works now. |
|
With the last change it now works as expected also on Windows. |
| include(BareosWindowsResource) | ||
| include(CheckIncludeFiles) | ||
|
|
||
| option(fd-client-sleep-inhibition |
There was a problem hiding this comment.
every other option is UPPER_SNAKE_CASE, why was kebab case chosen here ?
There was a problem hiding this comment.
Renamed to FD_CLIENT_SLEEP_INHIBITION
| 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) |
There was a problem hiding this comment.
This probably belongs in BareosCheckIncludes.cmake
There was a problem hiding this comment.
moved to BareosCheckIncludes.cmake
| target_compile_definitions(fd_objects_common | ||
| PRIVATE HAVE_FD_CLIENT_SLEEP_INHIBITION=1 | ||
| ) |
There was a problem hiding this comment.
Why do we not add this to config.h instead ?
There was a problem hiding this comment.
I guess this is only relevant for the fd.
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
Do we need this even without fd-client-sleep-inhibition ?
There was a problem hiding this comment.
Good point, changed to HAVE_DARWIN_OS AND FD_CLIENT_SLEEP_INHIBITION
| else() | ||
| target_link_libraries(fd_objects_common PRIVATE systemd) | ||
| endif() | ||
| endif() |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
Ok, good point, was refactored.
| [[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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Good point, os_suspension.h and os_suspension_{linux,darwin,win32}.cc were added.
There was a problem hiding this comment.
Also, now all OS check for the current state in the corresponding files.
| #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 |
There was a problem hiding this comment.
Same here. This should just be
#if ...
AllowOsSuspensions();
#endif
| // 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); } | ||
| } |
There was a problem hiding this comment.
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, ....).
There was a problem hiding this comment.
That makes sense. Was changed to condition variable.
There was a problem hiding this comment.
This is still a big loop. Where is the condition variable that you talked about ?
| #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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
That was addressed in the files mentioned above.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
core/src/filed/os_suspension_win32.cc (1)
37-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCheck 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 astatuscommand)—consider verifying thewindows_activeflag 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
📒 Files selected for processing (9)
core/cmake/BareosCheckIncludes.cmakecore/src/filed/CMakeLists.txtcore/src/filed/dir_cmd.cccore/src/filed/filed.cccore/src/filed/os_suspension.cccore/src/filed/os_suspension.hcore/src/filed/os_suspension_darwin.cccore/src/filed/os_suspension_linux.cccore/src/filed/os_suspension_win32.cc
🚧 Files skipped from review as they are similar to previous changes (1)
- core/src/filed/filed.cc
fe1dd8b to
b92f4c6
Compare
sebsura
left a comment
There was a problem hiding this comment.
There are merge conflicts
| // 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); } | ||
| } |
There was a problem hiding this comment.
This is still a big loop. Where is the condition variable that you talked about ?
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.
7062b03 to
6738dfc
Compare
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.
6738dfc to
13ffefc
Compare
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
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-toolto have some simple automated checks run and a proper changelog record added.General
Source code quality
Tests