Watch the launcher child process and surface errors as driver conditions. The driver no longer owns the `Ready` transition — the gateway promotes a sandbox to `Ready` the moment its supervisor session lands (see `openshell-server/src/compute/mod.rs`). This loop only handles the sad paths: the child process failing to start, exiting abnormally, or becoming unpollable. Those still surface as driver
(&self, sandbox_id: String)
| 2830 | /// abnormally, or becoming unpollable. Those still surface as driver |
| 2831 | /// `Error` conditions so the gateway can reason about a dead VM. |
| 2832 | async fn monitor_sandbox(&self, sandbox_id: String) { |
| 2833 | loop { |
| 2834 | let process = { |
| 2835 | let registry = self.registry.lock().await; |
| 2836 | let Some(record) = registry.get(&sandbox_id) else { |
| 2837 | return; |
| 2838 | }; |
| 2839 | let Some(process) = record.process.as_ref() else { |
| 2840 | return; |
| 2841 | }; |
| 2842 | process.clone() |
| 2843 | }; |
| 2844 | |
| 2845 | let exit_status = { |
| 2846 | let mut process = process.lock().await; |
| 2847 | if process.deleting { |
| 2848 | return; |
| 2849 | } |
| 2850 | match process.child.try_wait() { |
| 2851 | Ok(status) => status, |
| 2852 | Err(err) => { |
| 2853 | if let Some(snapshot) = self |
| 2854 | .set_snapshot_condition( |
| 2855 | &sandbox_id, |
| 2856 | error_condition("ProcessPollFailed", &err.to_string()), |
| 2857 | false, |
| 2858 | ) |
| 2859 | .await |
| 2860 | { |
| 2861 | self.publish_snapshot(snapshot); |
| 2862 | } |
| 2863 | self.publish_platform_event( |
| 2864 | sandbox_id.clone(), |
| 2865 | platform_event( |
| 2866 | "vm", |
| 2867 | "Warning", |
| 2868 | "ProcessPollFailed", |
| 2869 | format!("Failed to poll VM helper process: {err}"), |
| 2870 | ), |
| 2871 | ); |
| 2872 | return; |
| 2873 | } |
| 2874 | } |
| 2875 | }; |
| 2876 | |
| 2877 | if let Some(status) = exit_status { |
| 2878 | let message = status.code().map_or_else( |
| 2879 | || "VM process exited".to_string(), |
| 2880 | |code| format!("VM process exited with status {code}"), |
| 2881 | ); |
| 2882 | if let Some(snapshot) = self |
| 2883 | .set_snapshot_condition( |
| 2884 | &sandbox_id, |
| 2885 | error_condition("ProcessExited", &message), |
| 2886 | false, |
| 2887 | ) |
| 2888 | .await |
| 2889 | { |
no test coverage detected