diff --git a/src/bin/getty.rs b/src/bin/getty.rs index 6afb645771..c376f99c85 100644 --- a/src/bin/getty.rs +++ b/src/bin/getty.rs @@ -58,6 +58,10 @@ pub fn handle( // master_fd => PTY let handle_event = |event_id: usize| { + // The console<->PTY bridge must never panic on a transient read/write + // error: getty runs this while the login shell is alive, so a panic here + // kills the shell's I/O forwarding (input stops, output stops). Log and + // stop the current forwarding cycle instead; the event loop keeps going. if event_id as RawFd == tty_fd { let mut packet = [0; 4096]; loop { @@ -65,10 +69,15 @@ pub fn handle( Ok(0) => return, Ok(count) => count, Err(ref err) if err.errno() == EAGAIN => break, - Err(_) => panic!("getty: failed to read from TTY"), + Err(err) => { + eprintln!("getty: failed to read from TTY: {err}"); + return; + } }; - redox::write(master_fd as usize, &packet[..count]) - .expect("getty: failed to write master PTY"); + if let Err(err) = redox::write(master_fd as usize, &packet[..count]) { + eprintln!("getty: failed to write master PTY: {err}"); + break; + } } } else if event_id as RawFd == master_fd { let mut packet = [0; 4096]; @@ -77,10 +86,15 @@ pub fn handle( Ok(0) => return, Ok(count) => count, Err(ref err) if err.errno() == EAGAIN => break, - Err(_) => panic!("getty: failed to read from master TTY"), + Err(err) => { + eprintln!("getty: failed to read from master PTY: {err}"); + return; + } }; - redox::write(tty_fd as usize, &packet[1..count]) - .expect("getty: failed to write to TTY"); + if let Err(err) = redox::write(tty_fd as usize, &packet[1..count]) { + eprintln!("getty: failed to write to TTY: {err}"); + break; + } if packet[0] & 1 == 1 { let _ = redox::fsync(tty_fd as usize); } @@ -92,26 +106,36 @@ pub fn handle( handle_event(master_fd as usize); 'events: loop { - let sys_event = event_queue - .next() - .expect("getty: event queue stopped") - .expect("getty: failed to read event file"); + let sys_event = match event_queue.next() { + Some(Ok(event)) => event, + Some(Err(err)) => { + eprintln!("getty: failed to read event file: {err}; exiting bridge"); + break 'events; + } + None => { + eprintln!("getty: event queue stopped; exiting bridge"); + break 'events; + } + }; handle_event(sys_event.fd); match process.try_wait() { - Ok(status) => match status { - Some(_code) => break 'events, - None => (), - }, + Ok(Some(_code)) => break 'events, + Ok(None) => (), Err(err) => match err.kind() { ErrorKind::WouldBlock => (), - _ => panic!("getty: failed to wait on child: {:?}", err), + _ => { + eprintln!("getty: failed to wait on child: {err:?}; exiting bridge"); + break 'events; + } }, } } let _ = process.kill(); - process.wait().expect("getty: failed to wait on login"); + if let Err(err) = process.wait() { + eprintln!("getty: failed to wait on login: {err}"); + } } pub fn getpty(columns: u16, lines: u16) -> (RawFd, String) {