MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / start_thread

Method start_thread

vmm/src/serial_manager.rs:253–427  ·  view source on GitHub ↗
(&mut self, exit_evt: EventFd)

Source from the content-addressed store, hash-verified

251 }
252
253 pub fn start_thread(&mut self, exit_evt: EventFd) -> Result<()> {
254 // Don't allow this to be run if the handle exists
255 if self.handle.is_some() {
256 warn!("Tried to start multiple SerialManager threads, ignoring");
257 return Ok(());
258 }
259
260 let epoll_fd = self.epoll_fd.try_clone().map_err(Error::Epoll)?;
261 let transport = self.transport.clone();
262 let serial = self.serial.clone();
263 let pty_write_out = self.pty_write_out.clone();
264 let mut reader: Option<UnixStream> = None;
265
266 // In case of PTY, we want to be able to detect a connection on the
267 // other end of the PTY. This is done by detecting there's no event
268 // triggered on the epoll, which is the reason why we want the
269 // epoll_wait() function to return after the timeout expired.
270 // In case of TTY, we don't expect to detect such behavior, which is
271 // why we can afford to block until an actual event is triggered.
272 let timeout = if pty_write_out.is_some() { 500 } else { -1 };
273
274 let thread = thread::Builder::new()
275 .name("serial-manager".to_string())
276 .spawn(move || {
277 std::panic::catch_unwind(AssertUnwindSafe(move || {
278 let mut events =
279 [epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
280
281 loop {
282 let num_events =
283 match epoll::wait(epoll_fd.as_raw_fd(), timeout, &mut events[..]) {
284 Ok(res) => res,
285 Err(e) => {
286 if e.kind() == io::ErrorKind::Interrupted {
287 // It's well defined from the epoll_wait() syscall
288 // documentation that the epoll loop can be interrupted
289 // before any of the requested events occurred or the
290 // timeout expired. In both those cases, epoll_wait()
291 // returns an error of type EINTR, but this should not
292 // be considered as a regular error. Instead it is more
293 // appropriate to retry, by calling into epoll_wait().
294 continue;
295 }
296 return Err(Error::Epoll(e));
297 }
298 };
299
300 if matches!(transport, ConsoleTransport::Pty(_)) && num_events == 0 {
301 // This very specific case happens when the serial is connected
302 // to a PTY. We know EPOLLHUP is always present when there's nothing
303 // connected at the other end of the PTY. That's why getting no event
304 // means we can flush the output of the serial through the PTY.
305 Self::trigger_pty_flush(&serial, pty_write_out.as_ref())?;
306 continue;
307 }
308
309 for event in events.iter().take(num_events) {
310 let dispatch_event: EpollDispatch = event.data.into();

Callers 3

newMethod · 0.45
add_console_devicesMethod · 0.45

Calls 15

newFunction · 0.85
spawnMethod · 0.80
okMethod · 0.80
kindMethod · 0.80
takeMethod · 0.80
iterMethod · 0.80
try_cloneMethod · 0.45
cloneMethod · 0.45
as_raw_fdMethod · 0.45
shutdownMethod · 0.45
acceptMethod · 0.45
set_outMethod · 0.45

Tested by

no test coverage detected