-
Notifications
You must be signed in to change notification settings - Fork 382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cli: drop built-in pager_handle
when appropriate
#4187
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
use std::io::{IsTerminal as _, Stderr, StderrLock, Stdout, StdoutLock, Write}; | ||
use std::process::{Child, ChildStdin, Stdio}; | ||
use std::str::FromStr; | ||
use std::sync::{Arc, RwLock}; | ||
use std::thread::JoinHandle; | ||
use std::{env, fmt, io, mem}; | ||
|
||
|
@@ -45,7 +46,7 @@ enum UiOutput { | |
|
||
/// A builtin pager | ||
pub struct BuiltinPager { | ||
pager: MinusPager, | ||
pager: Arc<RwLock<Option<MinusPager>>>, | ||
dynamic_pager_thread: JoinHandle<()>, | ||
} | ||
|
||
|
@@ -56,8 +57,14 @@ impl Write for &BuiltinPager { | |
} | ||
|
||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||
let pager = self | ||
.pager | ||
.read() | ||
.unwrap() | ||
.clone() | ||
.ok_or_else(|| io::Error::from(io::ErrorKind::BrokenPipe))?; | ||
let string = std::str::from_utf8(buf).map_err(io::Error::other)?; | ||
self.pager.push_str(string).map_err(io::Error::other)?; | ||
pager.push_str(string).map_err(io::Error::other)?; | ||
Ok(buf.len()) | ||
} | ||
} | ||
|
@@ -70,6 +77,7 @@ impl Default for BuiltinPager { | |
|
||
impl BuiltinPager { | ||
pub fn finalize(self) { | ||
self.pager.write().unwrap().take(); | ||
let dynamic_pager_thread = self.dynamic_pager_thread; | ||
dynamic_pager_thread.join().unwrap(); | ||
} | ||
|
@@ -81,13 +89,24 @@ impl BuiltinPager { | |
pager | ||
.set_exit_strategy(minus::ExitStrategy::PagerQuit) | ||
.expect("Able to set the exit strategy"); | ||
let pager_handle = pager.clone(); | ||
let pager_handle = Arc::new(RwLock::new(Some(pager.clone()))); | ||
|
||
pager | ||
.add_exit_callback(Box::new({ | ||
let pager_handle = pager_handle.clone(); | ||
move || { | ||
pager_handle.write().unwrap().take(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to disable late BTW, this PR revealed that the current builtin pager is fundamentally broken. Because the backing channel is unbounded, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
(Just curious) What do you mean? Are you talking about the problem this PR solves or about a separate problem? Are you talking about something we do or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, AtomicBool sounds fine to me as far as this PR goes, but I'll mention that I was considering replacing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's kinda the same problem under the hood, but user might not notice. Basically, if the pager is minus, Our expectation is that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What would be symptoms of this? Running out of memory? Something more serious? Would anything short of redesigning minus help? Though, they might accept a PR to block on writes at some limit and return BrokenPipe after quitting. I think the pager Sapling used, streampager, was more carefully designed for huge inputs, but it seemed abandoned last I checked. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @yuja: It's true that we could use
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I would say As far as I understand the implementation, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the point that Like Erich, I liked the idea of making invalid states inexpressible, but I'm not sure about the downsides of RwLock and whether they are worth it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No? I just mean boolean flag is easier to follow than heavy lifting on interior mutability. BTW, judging from the discussion on Discord, it might be better to just switch to streampager. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If anyone is reading this, here is what seems like a nice book that discusses Atomic types: https://marabos.nl/atomics/atomics.html#atomic-load-and-store-operations |
||
} | ||
})) | ||
.unwrap(); | ||
|
||
BuiltinPager { | ||
pager, | ||
pager: pager_handle.clone(), | ||
dynamic_pager_thread: std::thread::spawn(move || { | ||
// This thread handles the actual paging. | ||
minus::dynamic_paging(pager_handle).unwrap(); | ||
let res = minus::dynamic_paging(pager); | ||
pager_handle.write().unwrap().take(); | ||
res.unwrap(); | ||
}), | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add a comment:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! This is one of the things I was hoping to do before taking this out of draft. 🙂 Will attend to this soon.