on master help sign in
improve reliability of shutdown
cb23399Skyler Hawthorne
helix-term/src/application.rs+52−20
@@ -937,26 +937,26 @@ impl Application {
937
937
938 self.event_loop(input_stream).await;
938 self.event_loop(input_stream).await;
939
939
940− let mut save_errs = Vec::new();
940+ // let mut save_errs = Vec::new();
941−
941+
942− for doc in self.editor.documents_mut() {
942+ // for doc in self.editor.documents_mut() {
943− if let Some(Err(err)) = doc.close().await {
943+ // if let Some(Err(err)) = doc.close().await {
944− save_errs.push((
944+ // save_errs.push((
945− doc.path()
945+ // doc.path()
946− .map(|path| path.to_string_lossy().into_owned())
946+ // .map(|path| path.to_string_lossy().into_owned())
947− .unwrap_or_else(|| "".into()),
947+ // .unwrap_or_else(|| "".into()),
948− err,
948+ // err,
949− ));
949+ // ));
950− }
950+ // }
951− }
951+ // }
952
952
953 let close_err = self.close().await.err();
953 let close_err = self.close().await.err();
954 restore_term()?;
954 restore_term()?;
955
955
956− for (path, err) in save_errs {
956+ // for (path, err) in save_errs {
957− self.editor.exit_code = 1;
957+ // self.editor.exit_code = 1;
958− eprintln!("Error closing '{}': {}", path, err);
958+ // eprintln!("Error closing '{}': {}", path, err);
959− }
959+ // }
960
960
961 if let Some(err) = close_err {
961 if let Some(err) = close_err {
962 self.editor.exit_code = 1;
962 self.editor.exit_code = 1;
@@ -967,12 +967,44 @@ impl Application {
967 }
967 }
968
968
969 pub async fn close(&mut self) -> anyhow::Result<()> {
969 pub async fn close(&mut self) -> anyhow::Result<()> {
970− self.jobs.finish().await?;
970+ // [NOTE] we intentionally do not return early for errors because we
971+ // want to try to run as much cleanup as we can, regardless of
972+ // errors along the way
971
973
972− if self.editor.close_language_servers(None).await.is_err() {
974+ let mut result = match self.jobs.finish().await {
973− log::error!("Timed out waiting for language servers to shutdown");
975+ Ok(_) => Ok(()),
976+ Err(err) => {
977+ log::error!("Error executing job: {}", err);
978+ Err(err)
979+ }
974 };
980 };
975
981
976− Ok(())
982+ for doc in self.editor.documents_mut() {
983+ if let Some(save_result) = doc.close().await {
984+ result = match save_result {
985+ Ok(_) => result,
986+ Err(err) => {
987+ if let Some(path) = doc.path() {
988+ log::error!(
989+ "Error saving document '{}': {}",
990+ path.to_string_lossy(),
991+ err
992+ );
993+ }
994+ Err(err)
995+ }
996+ };
997+ }
998+ }
999+
1000+ match self.editor.close_language_servers(None).await {
1001+ Ok(_) => result,
1002+ Err(_) => {
1003+ log::error!("Timed out waiting for language servers to shutdown");
1004+ Err(anyhow::format_err!(
1005+ "Timed out waiting for language servers to shutdown"
1006+ ))
1007+ }
1008+ }
977 }
1009 }
978}
1010}
helix-term/src/commands/typed.rs+7−1
@@ -1,5 +1,7 @@
1use std::ops::Deref;
1use std::ops::Deref;
2
2
3+use crate::job::Job;
4+
3use super::*;
5use super::*;
4
6
5use helix_view::{
7use helix_view::{
@@ -19,6 +21,8 @@ pub struct TypableCommand {
19}
21}
20
22
21fn quit(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
23fn quit(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) -> anyhow::Result<()> {
24+ log::info!("quitting...");
25+
22 if event != PromptEvent::Validate {
26 if event != PromptEvent::Validate {
23 return Ok(());
27 return Ok(());
24 }
28 }
@@ -274,7 +278,7 @@ fn write_impl(
274 doc.auto_format().map(|fmt| {
278 doc.auto_format().map(|fmt| {
275 let shared = fmt.shared();
279 let shared = fmt.shared();
276 let callback = make_format_callback(doc.id(), doc.version(), shared.clone());
280 let callback = make_format_callback(doc.id(), doc.version(), shared.clone());
277− jobs.callback(callback);
281+ jobs.add(Job::with_callback(callback).wait_before_exiting());
278 shared
282 shared
279 })
283 })
280 } else {
284 } else {
@@ -512,8 +516,10 @@ fn write_quit(
512 }
516 }
513
517
514 write_impl(cx, args.first(), false)?;
518 write_impl(cx, args.first(), false)?;
519+
515 let doc = doc_mut!(cx.editor);
520 let doc = doc_mut!(cx.editor);
516
521
522+ tokio::task::block_in_place(|| helix_lsp::block_on(cx.jobs.finish()))?;
517 tokio::task::block_in_place(|| helix_lsp::block_on(doc.try_flush_saves()))
523 tokio::task::block_in_place(|| helix_lsp::block_on(doc.try_flush_saves()))
518 .map(|result| result.map(|_| ()))
524 .map(|result| result.map(|_| ()))
519 .unwrap_or(Ok(()))?;
525 .unwrap_or(Ok(()))?;
helix-view/src/document.rs+15−2
@@ -551,6 +551,11 @@ impl Document {
551 bail!("saves are closed for this document!");
551 bail!("saves are closed for this document!");
552 }
552 }
553
553
554+ log::debug!(
555+ "submitting save of doc '{:?}'",
556+ self.path().map(|path| path.to_string_lossy())
557+ );
558+
554 // we clone and move text + path into the future so that we asynchronously save the current
559 // we clone and move text + path into the future so that we asynchronously save the current
555 // state without blocking any further edits.
560 // state without blocking any further edits.
556 let mut text = self.text().clone();
561 let mut text = self.text().clone();
@@ -695,7 +700,14 @@ impl Document {
695 self.set_last_saved_revision(event.revision);
700 self.set_last_saved_revision(event.revision);
696 false
701 false
697 }
702 }
703+ Err(err) => {
704+ log::error!(
705+ "error saving document {:?}: {}",
706+ self.path().map(|path| path.to_string_lossy()),
707+ err
708+ );
698− Err(_) => true,
709+ true
710+ }
699 };
711 };
700
712
701 final_result = Some(save_event);
713 final_result = Some(save_event);
@@ -1072,7 +1084,8 @@ impl Document {
1072 let current_revision = history.current_revision();
1084 let current_revision = history.current_revision();
1073 self.history.set(history);
1085 self.history.set(history);
1074 log::debug!(
1086 log::debug!(
1075− "modified - last saved: {}, current: {}",
1087+ "id {} modified - last saved: {}, current: {}",
1088+ self.id,
1076 self.last_saved_revision,
1089 self.last_saved_revision,
1077 current_revision
1090 current_revision
1078 );
1091 );
helix-view/src/editor.rs+6−2
@@ -816,12 +816,16 @@ impl Editor {
816
816
817 #[inline]
817 #[inline]
818 pub fn set_status<T: Into<Cow<'static, str>>>(&mut self, status: T) {
818 pub fn set_status<T: Into<Cow<'static, str>>>(&mut self, status: T) {
819+ let status = status.into();
820+ log::debug!("editor status: {}", status);
819− self.status_msg = Some((status.into(), Severity::Info));
821+ self.status_msg = Some((status, Severity::Info));
820 }
822 }
821
823
822 #[inline]
824 #[inline]
823 pub fn set_error<T: Into<Cow<'static, str>>>(&mut self, error: T) {
825 pub fn set_error<T: Into<Cow<'static, str>>>(&mut self, error: T) {
826+ let error = error.into();
827+ log::error!("editor error: {}", error);
824− self.status_msg = Some((error.into(), Severity::Error));
828+ self.status_msg = Some((error, Severity::Error));
825 }
829 }
826
830
827 #[inline]
831 #[inline]