← Back to issue list

Fix daemon stopping error during LXD container initialization

View original Github issue

Metadata

Project
craft-providers
Number
#871
Type
pull request
State
open
Author
copilot-swe-agent
Labels
Created
Updated
Closed

Current evaluation

Adds retry logic with exponential backoff to handle transient snapd socket activation errors during LXD container initialization. Has failing CI checks and unresolved review comments.

Suggested action: needs review

Reason: The PR addresses an open issue (#870) with a reasonable retry-based fix, but CI checks show multiple failing tests (ubuntu-24.04-arm, macos-13, minimum dependencies) and there are 4 unresolved review comments. Recent activity (6 days ago) suggests it's still active, but the CI failures and pending review require maintainer assessment before merge.

Impact: 55 Quick Win: 30.25 Staleness: 65 Complexity: 45 Confidence: 65

Issue body

- [x] Have you followed the guidelines for contributing? - [x] Have you signed the [CLA](http://www.ubuntu.com/legal/contributors/)? - [x] Have you successfully run `make lint && make test`? --- ## Description This PR fixes the intermittent "daemon is stopping to wait for socket activation" error that occurs during LXD container initialization when craft-providers attempts to wait for snap refreshes. ### Problem When creating and initializing LXD base containers, craft-providers fails with "daemon is stopping to wait for socket activation" error when running `snap watch --last=auto-refresh?`. This indicates that snapd inside the newly created container is in a transitional state and not yet ready to handle the command, causing the entire container setup to fail intermittently. ### Solution Implemented retry logic with exponential backoff in the `_disable_and_wait_for_snap_refresh` method to gracefully handle transient snapd states: - Maximum 5 retry attempts - Exponential backoff: 1s, 2s, 4s, 8s, 16s between retries - Only retries when stderr contains "daemon is stopping" - Other errors fail immediately without retry ## Changes Made ### Core Implementation **craft_providers/base.py**: - Added `time` module import - Modified `_disable_and_wait_for_snap_refresh` to implement retry logic with exponential backoff - Detects "daemon is stopping" error in stderr - Added clear comment documenting the wait time progression ### Tests Added comprehensive unit tests covering all retry scenarios: - **test_disable_and_wait_for_snap_refresh_retry_daemon_stopping**: Verifies successful retry after transient errors - **test_disable_and_wait_for_snap_refresh_retry_exhausted**: Verifies proper failure after exhausting all retries - **test_disable_and_wait_for_snap_refresh_non_transient_error**: Verifies immediate failure for non-transient errors Tests added to: - `tests/unit/bases/test_ubuntu_buildd.py` (3 new tests) - `tests/unit/bases/test_almalinux.py` (3 new tests) - `tests/unit/bases/test_centos_7.py` (3 new tests) ## Testing - ✅ All new tests pass (15 tests total) - ✅ All existing tests pass (438+ tests in ubuntu_buildd alone) - ✅ Linting and formatting verified with ruff - ✅ Type checking passed with mypy - ✅ Security scan (CodeQL) passed with no alerts ## Impact This fix addresses: - Intermittent build failures in charmcraft - CI/CD test failures (spread tests in charmcraft) - Container initialization reliability issues - Race conditions during snapd startup in newly created containers The solution is minimal and surgical, only adding retry logic for the specific transient error without changing the overall flow or behavior for other error conditions. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> ---- *This section details on the original issue you should resolve* <issue_title>snapd "daemon is stopping to wait for socket activation" error during LXD container initialization</issue_title> <issue_description>### Bug Description When craft-providers creates and initializes LXD base containers, it fails with "daemon is stopping to wait for socket activation" error when attempting to wait for snap refreshes. This causes builds to fail intermittently. ### To Reproduce ## Environment - Container OS: Ubuntu 22.04 (core22) - Host OS: Ubuntu 20.04 (in spread tests) - craft-providers version: ~3.1 (as used by charmcraft 4.0.0) - Affected method: `craft_providers.base._disable_and_wait_for_snap_refresh` ## Steps to Reproduce 1. Set up LXD on an Ubuntu system 2. Use craft-providers (via charmcraft or directly) to create a new base LXD container from Ubuntu 22.04 3. The failure occurs during base container setup when craft-providers runs: ```bash snap watch --last=auto-refresh? ``` ## Expected Behavior The container should be created successfully, with snapd fully initialized and ready to handle snap operations. ## Actual Behavior The command fails with: ``` error: daemon is stopping to wait for socket activation craft_providers.lxd.errors.LXDError: Failed to wait for snap refreshes to complete. ``` ## Error Details ### Error message: ``` error: daemon is stopping to wait for socket activation craft_providers.lxd.errors.LXDError: Failed to wait for snap refreshes to complete. * Command that failed: "lxc --project charmcraft exec local:base-instance-charmcraft-buildd-base-v71-3e75872519c3ea8f5604 -- env CRAFT_MANAGED_MODE=1 ... snap watch '--last=auto-refresh?'" * Command exit code: 1 * Command standard error output: b'error: daemon is stopping to wait for socket activation\n' ``` ### Full stack trace: ```python File "/snap/charmcraft/x1/lib/python3.12/site-packages/craft_providers/base.py", line 616, in _disable_and_wait_for_snap_refresh executor.execute_run( ["snap", "watch", "--last=auto-refresh?"], capture_output=True, check=True, ) File "/snap/charmcraft/x1/lib/python3.12/site-packages/craft_providers/lxd/lxd_instance.py", line 267, in execute_run return self.lxc.exec( File "/snap/charmcraft/x1/lib/python3.12/site-packages/craft_providers/lxd/lxc.py", line 528, in exec return runner(final_cmd, timeout=timeout, check=check, **kwargs) File "/snap/charmcraft/current/usr/lib/python3.12/subprocess.py", line 571, in run raise CalledProcessError(retcode, process.args, output=stdout, stderr=stderr) subprocess.CalledProcessError: Command [...] returned non-zero exit status 1. The above exception was the direct cause of the following exception: File "/snap/charmcraft/x1/lib/python3.12/site-packages/craft_providers/base.py", line 623, in _disable_and_wait_for_snap_refresh raise BaseConfigurationError( f"Failed to wait for snap refreshes to complete.\n" f"* Command that failed: {' '.join(cmd)!r}\n" f"* Command exit code: {error.returncode}\n" f"* Command standard error output: {error.stderr!r}" ) from error craft_providers.errors.BaseConfigurationError: Failed to wait for snap refreshes to complete. ``` ## Root Cause Analysis The error "daemon is stopping to wait for socket activation" indicates that snapd inside the newly created container is in a transitional state. This typically happens when: 1. **Socket activation is pending**: snapd.socket is enabled but the daemon hasn't fully started yet 2. **Service is restarting**: The daemon is transitioning between states 3. **Race condition**: snap commands are being executed before snapd is fully operational The current code in `craft_providers.base._disable_and_wait_for_snap_refresh()` (around line 616) doesn't handle this transient state, causing the entire container setup to fail. ## Impact - **Build failures**: Causes charmcraft builds to fail intermittently - **CI/CD failures**: Affects spread tests in charmcraft (e.g., smoketests/reactive, smoketests/different-dir) - **Reproducibility issues**: Intermittent nature makes it hard to debug and reproduce consistently - **Broader impact**: Affects any project using craft-providers to create fresh LXD containers ## Proposed Solutions ### Option 1: Add retry logic with exponential backoff (Recommended) Modify `_disable_and_wait_for_snap_refresh` to retry when encountering the "daemon is stopping" error: ```python def _disable_and_wait_for_snap_refresh(self, executor: Executor) -> None: """Disable and wait for snap refreshes with retry logic.""" # ... existing code for snap refresh --hold ... # Wait for pending snap refreshes with retry max_retries = 5 for attempt in range(max_retries): try: executor.execute_run( ["snap", "watch", "--last=auto-refresh?"], capture_output=True, check=True, ) bre... </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes canonical/craft-providers#870 <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Evaluation history

Date Model Scores Action Summary
qwen3.6-35b-a3b-mtp-q6
Impact: 55
Quick Win: 30.25
Staleness: 65
Complexity: 45
Confidence: 65
needs review Adds retry logic with exponential backoff to handle transient snapd socket activation errors during LXD container initialization. Has failing CI checks and unresolved review comments.
qwen/qwen3.6-35b-a3b
Staleness: 75
Complexity: 20
Confidence: 60
needs review Adds retry logic with exponential backoff to handle transient daemon stopping errors during LXD container initialization. Includes unit tests and passes most CI checks. Awaiting maintainer review after 7+ months of inactivity.
qwen3.6-35b-a3b-mtp-q6
Staleness: 85
Complexity: 20
Confidence: 70
close stale Implements retry logic with exponential backoff to handle transient snapd daemon stopping errors during LXD container initialization. Currently inactive for over 7 months with only bot comments and no maintainer engagement.
qwen3.6-35b-a3b-mtp-q6
Staleness: 75
Complexity: 30
Confidence: 75
needs review Adds retry logic with exponential backoff to handle transient snapd socket activation errors during LXD container initialization. Includes comprehensive tests and passes CI. Currently awaiting maintainer review after ~7 months of inactivity.

Update history

Date Change
updated

Related work

  • Related To: canonical/craft-providers#870 (confidence 95%)

    PR explicitly references fixing this open issue about the same snapd socket activation error

Related issues

Issue Project State Summary Similarity
#870 snapd "daemon is stopping to wait for socket activation" error during LXD container initialization craft-providers open Intermittent LXD container setup failure due to snapd socket activation race condition during snap refresh wait
74%