comparison rust/chg/src/uihandler.rs @ 44755:4b0185841058

rust-chg: do not terminate tokio runtime until pager exits We no longer need to spawn a task just to keep the pager handle. The pager handle can be held by ChgUiHandler since the handler itself is not consumed and recreated across async calls. Differential Revision: https://phab.mercurial-scm.org/D8449
author Yuya Nishihara <yuya@tcha.org>
date Sat, 11 Apr 2020 02:51:03 +0900
parents c794d0da5fb2
children 27fe8cc1338f
comparison
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?;