Timeout behavior inconsistency across Vagrant provisioner types
0 reputation · 17 Oct 2024, 08:46 UTC
0 reputation · 17 Oct 2024, 08:46 UTC
Vagrant documents that setting a timeout on a provisioner sends an interrupt signal when the limit is exceeded and marks the provision as failed. However, observed behavior differs: some provisioner types (e.g., shell) leave the virtual machine running after a timeout, while others (e.g., Ansible) appear to trigger a vagrant halt. The underlying decision point—whether Vagrant core or the specific provisioner implementation initiates the halt—is not clearly defined in the documentation.
Goal: clarify what determines the VM state after a provisioner timeout and whether users can enforce a consistent outcome across provisioner types.
Constraints: rely only on the documented timeout attributes and environment variables; avoid assuming undocumented internal signals.
Uncertainty: it is unclear if the halt behavior is configurable, hard‑coded per provisioner, or dependent on the provisioner’s exit handling.
Which provisioner types cause Vagrant to halt the VM on timeout?
Is the halt behavior controllable via Vagrantfile settings or environment variables?
Can users guarantee a uniform VM state (either always running or always halted) regardless of the provisioner used?
31775 reputation · 17 Oct 2024, 19:33 UTC
Which provisioner types cause Vagrant to halt the VM on timeout? Only provisioners that Vagrant can directly terminate—typically the shell provisioner and any provisioner that exposes a native --timeout (or equivalent) flag that Vagrant passes through—will trigger a vagrant halt when the timeout is exceeded. Provisioners that run their own client executables and do not expose a timeout flag (e.g., ansible, chef, puppet) usually leave the VM running after a Vagrant‑level timeout because Vagrant cannot forcefully stop the child process chain.
Is the halt behavior controllable via Vagrantfile settings or environment variables? No, Vagrant does not provide a global switch to force all provisioners to halt the VM on timeout. The behavior is determined by whether Vagrant can signal the provisioner’s process tree. You can influence it per‑provisioner by:
timeout on Linux).config.vm.provision :shell, timeout: N only for the shell provisioner.Can users guarantee a uniform VM state (always running or always halted) regardless of the provisioner used? Not out of the box. To guarantee a uniform outcome you must either:
Vagrant’s timeout logic is implemented in the core and applies only to the command it starts for a provisioner. For the shell provisioner, Vagrant starts /bin/sh directly and can send a SIGTERM when the timer expires, causing the VM to halt if the shell exits non‑zero. For provisioners that launch external executables, Vagrant can only signal the top‑level process; if that process spawns long‑running children (common in Chef, Ansible, Puppet), the signal may not reach them, and the VM remains running. Additionally, some provisioners use SSH to execute commands and treat Vagrant’s timeout as an SSH session timeout, not a playbook execution timeout.
vagrant up --debug and locate the line that starts the provisioner. Verify if a --timeout flag appears in the command.ansible or other non‑shell provisioners, check the provisioner’s own documentation for a timeout option (e.g., --timeout or --forks).# wrapper.sh
#!/usr/bin/env bash
# Use the Unix timeout utility
exec timeout $VAGRANT_TIMEOUT_CMD your_provisioner_command
Add to Vagrantfile:
config.vm.provision :shell, path: 'wrapper.sh', timeout: 300
vagrant up to confirm that a timeout now halts the VM as desired.To refine the recommendation, please confirm whether the provisioner you are using exposes a native timeout flag that Vagrant can forward. If it does, Vagrant will normally halt the VM on timeout; if not, you’ll need a wrapper approach.
Use comments to ask for clarification. Post a solution as an answer.
31,775 reputation · 17 Oct 2024, 18:52 UTC
One point worth adding to the earlier answer: the asymmetry isn't just about whether the VM halts — it's about what survives inside the guest. With the shell provisioner, Vagrant's timeout aborts the local wait over the communicator, but the command already running in the guest (e.g., a sleep 600 or a package install) is typically orphaned and keeps executing. So the VM is not merely "still running"; it may be actively mutating state while Vagrant has already reported failure. A follow-up vagrant provision can then race against the orphaned process — a common source of confusing lock errors (dpkg/apt locks are the classic case).
Two practical implications:
vagrant ssh -c 'pgrep -f your-command' before assuming the guest is idle.vagrant provision and then explicitly runs vagrant halt (or leaves the VM up) is the only reliable way to get a consistent outcome across provisioner types.Also treat any Ansible-triggered halt as version-sensitive: it likely reflects connection-cleanup behavior of the external ansible-playbook process, not core policy. Confirm with VAGRANT_LOG=debug on your specific Vagrant/plugin versions rather than assuming it will reproduce.