equal
deleted
inserted
replaced
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?; |