| 287 | } |
| 288 | |
| 289 | fn accept_connections( |
| 290 | mut listener: ReceiveListener, |
| 291 | terminate_fd: &EventFd, |
| 292 | guest_memory: &GuestMemoryAtomic<GuestMemoryMmap>, |
| 293 | ) -> Result<(), MigratableError> { |
| 294 | let mut threads: Vec<thread::JoinHandle<Result<(), MigratableError>>> = Vec::new(); |
| 295 | let mut first_err = loop { |
| 296 | let socket = match listener.abortable_accept(terminate_fd) { |
| 297 | Ok(socket) => socket, |
| 298 | Err(e) => break Err(e), |
| 299 | }; |
| 300 | let Some(mut socket) = socket else { |
| 301 | break Ok(()); |
| 302 | }; |
| 303 | |
| 304 | if threads.len() >= MAX_MIGRATION_CONNECTIONS as usize { |
| 305 | break Err(MigratableError::MigrateReceive(anyhow!( |
| 306 | "Received more than {MAX_MIGRATION_CONNECTIONS} additional migration connections." |
| 307 | ))); |
| 308 | } |
| 309 | |
| 310 | let guest_memory = guest_memory.clone(); |
| 311 | let terminate_fd = match terminate_fd |
| 312 | .try_clone() |
| 313 | .context("Error cloning terminate fd") |
| 314 | .map_err(MigratableError::MigrateReceive) |
| 315 | { |
| 316 | Ok(terminate_fd) => terminate_fd, |
| 317 | Err(e) => break Err(e), |
| 318 | }; |
| 319 | |
| 320 | match thread::Builder::new() |
| 321 | .name(format!("migrate-receive-memory-{}", threads.len()).to_owned()) |
| 322 | .spawn(move || { |
| 323 | Self::worker_receive_memory(&mut socket, &terminate_fd, &guest_memory) |
| 324 | }) { |
| 325 | Ok(t) => threads.push(t), |
| 326 | Err(e) => { |
| 327 | error!("Error spawning receive-memory thread: {e}"); |
| 328 | break Err(MigratableError::MigrateReceive( |
| 329 | anyhow!(e).context("Error spawning receive-memory thread"), |
| 330 | )); |
| 331 | } |
| 332 | } |
| 333 | }; |
| 334 | |
| 335 | if first_err.is_err() { |
| 336 | warn!("Signaling termination due to an error while accepting connections."); |
| 337 | let _ = terminate_fd.write(1); |
| 338 | } |
| 339 | |
| 340 | info!("Stopped accepting additional connections. Cleaning up threads."); |
| 341 | |
| 342 | // We only return the first error we encounter here. |
| 343 | for thread in threads { |
| 344 | let err = match thread.join() { |
| 345 | Ok(Ok(())) => None, |
| 346 | Ok(Err(e)) => Some(e), |