rust/chg/src/uihandler.rs
changeset 44755 4b0185841058
parent 44750 c794d0da5fb2
child 44756 27fe8cc1338f
equal deleted inserted replaced
44754:9fc9526e283a 44755:4b0185841058
     7 use std::io;
     7 use std::io;
     8 use std::os::unix::io::AsRawFd;
     8 use std::os::unix::io::AsRawFd;
     9 use std::os::unix::process::ExitStatusExt;
     9 use std::os::unix::process::ExitStatusExt;
    10 use std::process::Stdio;
    10 use std::process::Stdio;
    11 use tokio;
    11 use tokio;
    12 use tokio::process::{ChildStdin, Command};
    12 use tokio::process::{Child, ChildStdin, Command};
    13 
    13 
    14 use crate::message::CommandSpec;
    14 use crate::message::CommandSpec;
    15 use crate::procutil;
    15 use crate::procutil;
    16 
    16 
    17 /// Callback to process shell command requests received from server.
    17 /// Callback to process shell command requests received from server.
    29     /// Returns command exit code (positive) or signal number (negative).
    29     /// Returns command exit code (positive) or signal number (negative).
    30     async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32>;
    30     async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32>;
    31 }
    31 }
    32 
    32 
    33 /// Default cHg implementation to process requests received from server.
    33 /// Default cHg implementation to process requests received from server.
    34 pub struct ChgUiHandler {}
    34 pub struct ChgUiHandler {
       
    35     pager: Option<Child>,
       
    36 }
    35 
    37 
    36 impl ChgUiHandler {
    38 impl ChgUiHandler {
    37     pub fn new() -> ChgUiHandler {
    39     pub fn new() -> ChgUiHandler {
    38         ChgUiHandler {}
    40         ChgUiHandler { pager: None }
       
    41     }
       
    42 
       
    43     /// Waits until the pager process exits.
       
    44     pub async fn wait_pager(&mut self) -> io::Result<()> {
       
    45         if let Some(p) = self.pager.take() {
       
    46             p.await?;
       
    47         }
       
    48         Ok(())
    39     }
    49     }
    40 }
    50 }
    41 
    51 
    42 #[async_trait]
    52 #[async_trait]
    43 impl SystemHandler for ChgUiHandler {
    53 impl SystemHandler for ChgUiHandler {
    49         procutil::set_blocking_fd(pin.as_raw_fd())?;
    59         procutil::set_blocking_fd(pin.as_raw_fd())?;
    50         // TODO: if pager exits, notify the server with SIGPIPE immediately.
    60         // TODO: if pager exits, notify the server with SIGPIPE immediately.
    51         // otherwise the server won't get SIGPIPE if it does not write
    61         // otherwise the server won't get SIGPIPE if it does not write
    52         // anything. (issue5278)
    62         // anything. (issue5278)
    53         // kill(peerpid, SIGPIPE);
    63         // kill(peerpid, SIGPIPE);
    54         tokio::spawn(async { pager.await }); // just ignore errors
    64         self.pager = Some(pager);
    55         Ok(pin)
    65         Ok(pin)
    56     }
    66     }
    57 
    67 
    58     async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> {
    68     async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> {
    59         let status = new_shell_command(&spec).spawn()?.await?;
    69         let status = new_shell_command(&spec).spawn()?.await?;