Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
termion
termion
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 61
    • Issues 61
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 20
    • Merge Requests 20
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • redox-os
  • termiontermion
  • Issues
  • #158

Closed
Open
Opened Sep 07, 2018 by Magnus Bergmark@Mange

Dropping of AlternateScreen does not flush stdout

When dropping alternate screen stdout is not flushed, leading to messages on stderr disappearing, or other processes using the same stdout not having any output visible.

See https://gitlab.redox-os.org/redox-os/termion/blob/d2945cd36c452824aeabd5d7c13980d9567eb8a2/src/screen.rs#L63-67

Here is a sample bin showing the issue:

extern crate termion;
use std::io;
use std::io::Write;
use termion::raw::IntoRawMode;

fn main() {
    let raw = io::stdout().into_raw_mode().unwrap();
    let screen = termion::screen::AlternateScreen::from(raw);

    println!("This is stdout in alt screen.\r");
    eprintln!("This is stderr in alt screen.\r");
    ::std::thread::sleep(::std::time::Duration::from_secs(1));

    drop(screen);

    // Comment this out to get both messages displayed:
    // io::stdout().flush().ok();

    eprintln!("This is stderr outside alt screen.\r");
    println!("This is stdout outside alt screen.\r");
}

First two messages are shown for a second, then only the message on stdout is displayed after the screen is restored. If stdout is flushed before, then the alternate screen is really stopped before anything is written to stderr. As it is now, the two buffers are flushed independently.

This also causes problems with things like this pseudo code:

fn main() {
  let command = select_command_in_alternate_screen()?;
  fork_exec_wait(command);
  println!("Done");
}

fn select_command_in_alternate_screen() -> Result<String, ()> {
  let mut terminal = setup_alternate_screen();
  // …
  return Ok(command);
  // implied drop(terminal) at the end of the function
}

The forked process (created using std::process::Command, for example) inherits the same stdout and stderr FDs and starts writing to them before this process has flushed its buffers, so output on both stdout and stderr is lost as soon as the "Done" message is finally flushed.

I think manually flushing at the drop means that it would be a lot easier to use alternate screens in RAII-patterns that Rust is so good at. Right now I manually need to place flush calls at each call site after a function using an alternate screen to be sure no message after it is lost.

Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: redox-os/termion#158