feat(core): improve exit handling
This commit is contained in:
		
							parent
							
								
									cba94607fa
								
							
						
					
					
						commit
						39758e2b9a
					
				| 
						 | 
					@ -23,9 +23,7 @@ use anyhow::Result;
 | 
				
			||||||
use crossbeam::channel::{Sender};
 | 
					use crossbeam::channel::{Sender};
 | 
				
			||||||
use log::{error, warn};
 | 
					use log::{error, warn};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::ipc::IPCEvent;
 | 
					use crate::{exit_code::DAEMON_SUCCESS, ipc::IPCEvent};
 | 
				
			||||||
 | 
					 | 
				
			||||||
use super::ExitCode;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn initialize_and_spawn(runtime_dir: &Path, exit_notify: Sender<i32>) -> Result<()> {
 | 
					pub fn initialize_and_spawn(runtime_dir: &Path, exit_notify: Sender<i32>) -> Result<()> {
 | 
				
			||||||
  let receiver = crate::ipc::spawn_daemon_ipc_server(runtime_dir)?;
 | 
					  let receiver = crate::ipc::spawn_daemon_ipc_server(runtime_dir)?;
 | 
				
			||||||
| 
						 | 
					@ -37,7 +35,7 @@ pub fn initialize_and_spawn(runtime_dir: &Path, exit_notify: Sender<i32>) -> Res
 | 
				
			||||||
        Ok(event) => {
 | 
					        Ok(event) => {
 | 
				
			||||||
          match event {
 | 
					          match event {
 | 
				
			||||||
            IPCEvent::Exit => {
 | 
					            IPCEvent::Exit => {
 | 
				
			||||||
              if let Err(err) = exit_notify.send(ExitCode::Success as i32) {
 | 
					              if let Err(err) = exit_notify.send(DAEMON_SUCCESS) {
 | 
				
			||||||
                error!("experienced error while sending exit signal from daemon ipc handler: {}", err);
 | 
					                error!("experienced error while sending exit signal from daemon ipc handler: {}", err);
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,20 +27,12 @@ use espanso_ipc::IPCClient;
 | 
				
			||||||
use espanso_path::Paths;
 | 
					use espanso_path::Paths;
 | 
				
			||||||
use log::{error, info, warn};
 | 
					use log::{error, info, warn};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{exit_code::{DAEMON_ALREADY_RUNNING, DAEMON_GENERAL_ERROR, DAEMON_SUCCESS, WORKER_EXIT_ALL_PROCESSES, WORKER_SUCCESS}, ipc::{create_ipc_client_to_worker, IPCEvent}, lock::{acquire_daemon_lock, acquire_worker_lock}};
 | 
				
			||||||
  ipc::{create_ipc_client_to_worker, IPCEvent},
 | 
					 | 
				
			||||||
  lock::{acquire_daemon_lock, acquire_worker_lock},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{CliModule, CliModuleArgs};
 | 
					use super::{CliModule, CliModuleArgs};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod ipc;
 | 
					mod ipc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum ExitCode {
 | 
					 | 
				
			||||||
  Success = 0,
 | 
					 | 
				
			||||||
  ExitCodeUnwrapError = 100,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub fn new() -> CliModule {
 | 
					pub fn new() -> CliModule {
 | 
				
			||||||
  #[allow(clippy::needless_update)]
 | 
					  #[allow(clippy::needless_update)]
 | 
				
			||||||
  CliModule {
 | 
					  CliModule {
 | 
				
			||||||
| 
						 | 
					@ -63,7 +55,7 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
 | 
				
			||||||
  let lock_file = acquire_daemon_lock(&paths.runtime);
 | 
					  let lock_file = acquire_daemon_lock(&paths.runtime);
 | 
				
			||||||
  if lock_file.is_none() {
 | 
					  if lock_file.is_none() {
 | 
				
			||||||
    error!("daemon is already running!");
 | 
					    error!("daemon is already running!");
 | 
				
			||||||
    return 1;
 | 
					    return DAEMON_ALREADY_RUNNING;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: we might need to check preconditions: accessibility on macOS, presence of binaries on Linux, etc
 | 
					  // TODO: we might need to check preconditions: accessibility on macOS, presence of binaries on Linux, etc
 | 
				
			||||||
| 
						 | 
					@ -87,18 +79,26 @@ fn daemon_main(args: CliModuleArgs) -> i32 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // TODO: start file watcher thread
 | 
					  // TODO: start file watcher thread
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let mut exit_code: i32 = ExitCode::Success as i32;
 | 
					  let mut exit_code: i32 = DAEMON_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loop {
 | 
					  loop {
 | 
				
			||||||
    select! {
 | 
					    select! {
 | 
				
			||||||
      recv(exit_signal) -> code => {
 | 
					      recv(exit_signal) -> code => {
 | 
				
			||||||
        match code {
 | 
					        match code {
 | 
				
			||||||
          Ok(code) => {
 | 
					          Ok(code) => {
 | 
				
			||||||
            exit_code = code
 | 
					            match code {
 | 
				
			||||||
 | 
					              WORKER_EXIT_ALL_PROCESSES => {
 | 
				
			||||||
 | 
					                info!("worker requested a general exit, quitting the daemon");
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              _ => {
 | 
				
			||||||
 | 
					                error!("received unexpected exit code from worker {}, exiting", code);
 | 
				
			||||||
 | 
					                exit_code = code
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          Err(err) => {
 | 
					          Err(err) => {
 | 
				
			||||||
            error!("received error when unwrapping exit_code: {}", err);
 | 
					            error!("received error when unwrapping exit_code: {}", err);
 | 
				
			||||||
            exit_code = ExitCode::ExitCodeUnwrapError as i32;
 | 
					            exit_code = DAEMON_GENERAL_ERROR;
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
| 
						 | 
					@ -177,11 +177,7 @@ fn spawn_worker(paths: &Paths, exit_notify: Sender<i32>) {
 | 
				
			||||||
      let result = child.wait();
 | 
					      let result = child.wait();
 | 
				
			||||||
      if let Ok(status) = result {
 | 
					      if let Ok(status) = result {
 | 
				
			||||||
        if let Some(code) = status.code() {
 | 
					        if let Some(code) = status.code() {
 | 
				
			||||||
          if code != 0 {
 | 
					          if code != WORKER_SUCCESS {
 | 
				
			||||||
            error!(
 | 
					 | 
				
			||||||
              "worker process exited with non-zero code: {}, exiting",
 | 
					 | 
				
			||||||
              code
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            exit_notify
 | 
					            exit_notify
 | 
				
			||||||
              .send(code)
 | 
					              .send(code)
 | 
				
			||||||
              .expect("unable to forward worker exit code");
 | 
					              .expect("unable to forward worker exit code");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,8 +18,7 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
  cell::RefCell,
 | 
					  collections::{HashSet},
 | 
				
			||||||
  collections::{HashMap, HashSet},
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::engine::{dispatch::ModeProvider, process::MatchFilter};
 | 
					use crate::engine::{dispatch::ModeProvider, process::MatchFilter};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ pub fn initialize_and_spawn(
 | 
				
			||||||
  ui_remote: Box<dyn UIRemote>,
 | 
					  ui_remote: Box<dyn UIRemote>,
 | 
				
			||||||
  exit_signal: Receiver<()>,
 | 
					  exit_signal: Receiver<()>,
 | 
				
			||||||
  ui_event_receiver: Receiver<UIEvent>,
 | 
					  ui_event_receiver: Receiver<UIEvent>,
 | 
				
			||||||
) -> Result<JoinHandle<()>> {
 | 
					) -> Result<JoinHandle<bool>> {
 | 
				
			||||||
  let handle = std::thread::Builder::new()
 | 
					  let handle = std::thread::Builder::new()
 | 
				
			||||||
    .name("engine thread".to_string())
 | 
					    .name("engine thread".to_string())
 | 
				
			||||||
    .spawn(move || {
 | 
					    .spawn(move || {
 | 
				
			||||||
| 
						 | 
					@ -154,10 +154,12 @@ pub fn initialize_and_spawn(
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
 | 
					      let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
 | 
				
			||||||
      engine.run();
 | 
					      let exit_all_processes = engine.run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      info!("engine eventloop has terminated, propagating exit event...");
 | 
					      info!("engine eventloop has terminated, propagating exit event...");
 | 
				
			||||||
      ui_remote.exit();
 | 
					      ui_remote.exit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      exit_all_processes
 | 
				
			||||||
    })?;
 | 
					    })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Ok(handle)
 | 
					  Ok(handle)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ impl<'a> funnel::Source<'a> for ExitSource<'a> {
 | 
				
			||||||
      .expect("unable to select data from ExitSource receiver");
 | 
					      .expect("unable to select data from ExitSource receiver");
 | 
				
			||||||
    Event {
 | 
					    Event {
 | 
				
			||||||
      source_id: self.sequencer.next_id(),
 | 
					      source_id: self.sequencer.next_id(),
 | 
				
			||||||
      etype: EventType::ExitRequested,
 | 
					      etype: EventType::ExitRequested(false),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
use crossbeam::channel::unbounded;
 | 
					use crossbeam::channel::unbounded;
 | 
				
			||||||
use log::{error, info};
 | 
					use log::{error, info};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::lock::acquire_worker_lock;
 | 
					use crate::{exit_code::{WORKER_ALREADY_RUNNING, WORKER_EXIT_ALL_PROCESSES, WORKER_GENERAL_ERROR, WORKER_SUCCESS}, lock::acquire_worker_lock};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use self::ui::util::convert_icon_paths_to_tray_vec;
 | 
					use self::ui::util::convert_icon_paths_to_tray_vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@ fn worker_main(args: CliModuleArgs) -> i32 {
 | 
				
			||||||
  let lock_file = acquire_worker_lock(&paths.runtime);
 | 
					  let lock_file = acquire_worker_lock(&paths.runtime);
 | 
				
			||||||
  if lock_file.is_none() {
 | 
					  if lock_file.is_none() {
 | 
				
			||||||
    error!("worker is already running!");
 | 
					    error!("worker is already running!");
 | 
				
			||||||
    return 1;
 | 
					    return WORKER_ALREADY_RUNNING;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let config_store = args
 | 
					  let config_store = args
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ fn worker_main(args: CliModuleArgs) -> i32 {
 | 
				
			||||||
  let (engine_ui_event_sender, engine_ui_event_receiver) = unbounded();
 | 
					  let (engine_ui_event_sender, engine_ui_event_receiver) = unbounded();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Initialize the engine on another thread and start it
 | 
					  // Initialize the engine on another thread and start it
 | 
				
			||||||
  engine::initialize_and_spawn(
 | 
					  let engine_handle = engine::initialize_and_spawn(
 | 
				
			||||||
    paths.clone(),
 | 
					    paths.clone(),
 | 
				
			||||||
    config_store,
 | 
					    config_store,
 | 
				
			||||||
    match_store,
 | 
					    match_store,
 | 
				
			||||||
| 
						 | 
					@ -98,13 +98,28 @@ fn worker_main(args: CliModuleArgs) -> i32 {
 | 
				
			||||||
  ipc::initialize_and_spawn(&paths.runtime, engine_exit_notify)
 | 
					  ipc::initialize_and_spawn(&paths.runtime, engine_exit_notify)
 | 
				
			||||||
    .expect("unable to initialize IPC server");
 | 
					    .expect("unable to initialize IPC server");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  eventloop.run(Box::new(move |event| {
 | 
					  eventloop
 | 
				
			||||||
    if let Err(error) = engine_ui_event_sender.send(event) {
 | 
					    .run(Box::new(move |event| {
 | 
				
			||||||
      error!("unable to send UIEvent to engine: {}", error);
 | 
					      if let Err(error) = engine_ui_event_sender.send(event) {
 | 
				
			||||||
 | 
					        error!("unable to send UIEvent to engine: {}", error);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }))
 | 
				
			||||||
 | 
					    .expect("unable to run main eventloop");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  info!("waiting for engine exit mode...");
 | 
				
			||||||
 | 
					  match engine_handle.join() {
 | 
				
			||||||
 | 
					    Ok(exit_all_processes) => {
 | 
				
			||||||
 | 
					      if exit_all_processes {
 | 
				
			||||||
 | 
					        info!("exiting worker process and daemon...");
 | 
				
			||||||
 | 
					        return WORKER_EXIT_ALL_PROCESSES;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        info!("exiting worker process...");
 | 
				
			||||||
 | 
					        return WORKER_SUCCESS;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })).expect("unable to run main eventloop");
 | 
					    Err(err) => {
 | 
				
			||||||
 | 
					      error!("unable to read engine exit mode: {:?}", err);
 | 
				
			||||||
  info!("exiting worker process...");
 | 
					      return WORKER_GENERAL_ERROR;
 | 
				
			||||||
   
 | 
					    }
 | 
				
			||||||
  0
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,8 +48,8 @@ impl Event {
 | 
				
			||||||
pub enum EventType {
 | 
					pub enum EventType {
 | 
				
			||||||
  NOOP,
 | 
					  NOOP,
 | 
				
			||||||
  ProcessingError(String),
 | 
					  ProcessingError(String),
 | 
				
			||||||
  ExitRequested,
 | 
					  ExitRequested(bool),  // If true, exit also the daemon process and not just the worker
 | 
				
			||||||
  Exit,
 | 
					  Exit(bool),
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Inputs
 | 
					  // Inputs
 | 
				
			||||||
  Keyboard(input::KeyboardEvent),
 | 
					  Keyboard(input::KeyboardEvent),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,15 +41,15 @@ impl <'a> Engine<'a> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pub fn run(&mut self) {
 | 
					  pub fn run(&mut self) -> bool {
 | 
				
			||||||
    'main: loop {
 | 
					    loop {
 | 
				
			||||||
      match self.funnel.receive() {
 | 
					      match self.funnel.receive() {
 | 
				
			||||||
        FunnelResult::Event(event) => {
 | 
					        FunnelResult::Event(event) => {
 | 
				
			||||||
          let processed_events = self.processor.process(event);
 | 
					          let processed_events = self.processor.process(event);
 | 
				
			||||||
          for event in processed_events {
 | 
					          for event in processed_events {
 | 
				
			||||||
            if let EventType::Exit = &event.etype {
 | 
					            if let EventType::Exit(exit_all_processes) = &event.etype {
 | 
				
			||||||
              debug!("exit event received, exiting engine");
 | 
					              debug!("exit event received, exiting engine");
 | 
				
			||||||
              break 'main;
 | 
					              return *exit_all_processes;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.dispatcher.dispatch(event);
 | 
					            self.dispatcher.dispatch(event);
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ impl <'a> Engine<'a> {
 | 
				
			||||||
        } 
 | 
					        } 
 | 
				
			||||||
        FunnelResult::EndOfStream => {
 | 
					        FunnelResult::EndOfStream => {
 | 
				
			||||||
          debug!("end of stream received");
 | 
					          debug!("end of stream received");
 | 
				
			||||||
          break;
 | 
					          return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,14 @@
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::super::Middleware;
 | 
					use super::super::Middleware;
 | 
				
			||||||
use crate::engine::{event::{Event, EventType, ui::{MenuItem, ShowContextMenuEvent, SimpleMenuItem}}};
 | 
					use crate::engine::event::{
 | 
				
			||||||
 | 
					  ui::{MenuItem, ShowContextMenuEvent, SimpleMenuItem},
 | 
				
			||||||
 | 
					  Event, EventType,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ContextMenuMiddleware {
 | 
					const CONTEXT_ITEM_EXIT: u32 = 0;
 | 
				
			||||||
}
 | 
					
 | 
				
			||||||
 | 
					pub struct ContextMenuMiddleware {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ContextMenuMiddleware {
 | 
					impl ContextMenuMiddleware {
 | 
				
			||||||
  pub fn new() -> Self {
 | 
					  pub fn new() -> Self {
 | 
				
			||||||
| 
						 | 
					@ -35,30 +39,38 @@ impl Middleware for ContextMenuMiddleware {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
 | 
					  fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
 | 
				
			||||||
    if let EventType::TrayIconClicked = event.etype {
 | 
					    match &event.etype {
 | 
				
			||||||
      // TODO: fetch top matches for the active config to be added
 | 
					      EventType::TrayIconClicked => {
 | 
				
			||||||
 | 
					        // TODO: fetch top matches for the active config to be added
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // TODO: my idea is to use a set of reserved u32 ids for built-in
 | 
					        // TODO: my idea is to use a set of reserved u32 ids for built-in
 | 
				
			||||||
      // actions such as Exit, Open Editor etc
 | 
					        // actions such as Exit, Open Editor etc
 | 
				
			||||||
      // then we need some u32 for the matches, so we need to create
 | 
					        // then we need some u32 for the matches, so we need to create
 | 
				
			||||||
      // a mapping structure match_id <-> context-menu-id
 | 
					        // a mapping structure match_id <-> context-menu-id
 | 
				
			||||||
      return Event::caused_by(
 | 
					        return Event::caused_by(
 | 
				
			||||||
        event.source_id,
 | 
					          event.source_id,
 | 
				
			||||||
        EventType::ShowContextMenu(ShowContextMenuEvent {
 | 
					          EventType::ShowContextMenu(ShowContextMenuEvent {
 | 
				
			||||||
          // TODO: add actual entries
 | 
					            // TODO: add actual entries
 | 
				
			||||||
          items: vec![
 | 
					            items: vec![MenuItem::Simple(SimpleMenuItem {
 | 
				
			||||||
            MenuItem::Simple(SimpleMenuItem {
 | 
					              id: CONTEXT_ITEM_EXIT,
 | 
				
			||||||
              id: 0,
 | 
					 | 
				
			||||||
              label: "Exit espanso".to_string(),
 | 
					              label: "Exit espanso".to_string(),
 | 
				
			||||||
            })
 | 
					            })],
 | 
				
			||||||
          ]
 | 
					          }),
 | 
				
			||||||
        }),
 | 
					        );
 | 
				
			||||||
      )
 | 
					      }
 | 
				
			||||||
 | 
					      EventType::ContextMenuClicked(context_click_event) => {
 | 
				
			||||||
 | 
					        match context_click_event.context_item_id {
 | 
				
			||||||
 | 
					          CONTEXT_ITEM_EXIT => {
 | 
				
			||||||
 | 
					            Event::caused_by(event.source_id, EventType::ExitRequested(true))
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          custom => {
 | 
				
			||||||
 | 
					            // TODO: handle dynamic items
 | 
				
			||||||
 | 
					            todo!()
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      _ => event,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: handle context menu clicks
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    event
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,9 +36,9 @@ impl Middleware for ExitMiddleware {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
 | 
					  fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
 | 
				
			||||||
    if let EventType::ExitRequested = &event.etype {
 | 
					    if let EventType::ExitRequested(exit_all_processes) = &event.etype {
 | 
				
			||||||
      debug!("received ExitRequested event, dispatching exit");
 | 
					      debug!("received ExitRequested event with 'exit_all_processes: {}', dispatching exit", exit_all_processes);
 | 
				
			||||||
      return Event::caused_by(event.source_id, EventType::Exit);
 | 
					      return Event::caused_by(event.source_id, EventType::Exit(*exit_all_processes));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    event
 | 
					    event
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								espanso/src/exit_code.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								espanso/src/exit_code.rs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of espanso.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2019-2021 Federico Terzi
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * espanso is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * espanso is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const WORKER_SUCCESS: i32 = 0;
 | 
				
			||||||
 | 
					pub const WORKER_ALREADY_RUNNING: i32 = 1;
 | 
				
			||||||
 | 
					pub const WORKER_GENERAL_ERROR: i32 = 2;
 | 
				
			||||||
 | 
					pub const WORKER_EXIT_ALL_PROCESSES: i32 = 101;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const DAEMON_SUCCESS: i32 = 0;
 | 
				
			||||||
 | 
					pub const DAEMON_ALREADY_RUNNING: i32 = 1;
 | 
				
			||||||
 | 
					pub const DAEMON_GENERAL_ERROR: i32 = 2;
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ use crate::cli::LogMode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod cli;
 | 
					mod cli;
 | 
				
			||||||
mod engine;
 | 
					mod engine;
 | 
				
			||||||
 | 
					mod exit_code;
 | 
				
			||||||
mod gui;
 | 
					mod gui;
 | 
				
			||||||
mod ipc;
 | 
					mod ipc;
 | 
				
			||||||
mod lock;
 | 
					mod lock;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user