From 0dde08b97b422fa84874b3579d0f41a51a873a56 Mon Sep 17 00:00:00 2001 From: Xavier L'Heureux <xavier.lheureux@icloud.com> Date: Fri, 31 May 2019 12:18:12 -0400 Subject: [PATCH] Change the variable type for previous_job --- src/lib/builtins/job_control.rs | 14 +++-- src/lib/shell/mod.rs | 4 +- src/lib/shell/pipe_exec/job_control.rs | 71 ++++++++++---------------- 3 files changed, 36 insertions(+), 53 deletions(-) diff --git a/src/lib/builtins/job_control.rs b/src/lib/builtins/job_control.rs index ed93cff3..7ea8a41a 100644 --- a/src/lib/builtins/job_control.rs +++ b/src/lib/builtins/job_control.rs @@ -74,9 +74,8 @@ pub fn jobs(shell: &mut Shell) { /// If the job is stopped, the job will be resumed. /// If multiple jobs are given, then only the last job's exit status will be returned. pub fn fg(shell: &mut Shell, args: &[small::String]) -> i32 { - fn fg_job(shell: &mut Shell, njob: u32) -> i32 { - if let Some(job) = shell.background_jobs().iter().nth(njob as usize).filter(|p| p.exists()) - { + fn fg_job(shell: &mut Shell, njob: usize) -> i32 { + if let Some(job) = shell.background_jobs().iter().nth(njob).filter(|p| p.exists()) { // Give the bg task the foreground, and wait for it to finish. Also resume it if it // isn't running shell.set_bg_task_in_foreground(job.pid(), !job.is_running()) @@ -97,7 +96,7 @@ pub fn fg(shell: &mut Shell, args: &[small::String]) -> i32 { }; } else { for arg in args { - match arg.parse::<u32>() { + match arg.parse::<usize>() { Ok(njob) => status = fg_job(shell, njob), Err(_) => { eprintln!("ion: fg: {} is not a valid job number", arg); @@ -111,9 +110,8 @@ pub fn fg(shell: &mut Shell, args: &[small::String]) -> i32 { /// Resumes a stopped background process, if it was stopped. pub fn bg(shell: &mut Shell, args: &[small::String]) -> i32 { - fn bg_job(shell: &mut Shell, njob: u32) -> bool { - if let Some(job) = shell.background_jobs().iter().nth(njob as usize).filter(|p| p.exists()) - { + fn bg_job(shell: &mut Shell, njob: usize) -> bool { + if let Some(job) = shell.background_jobs().iter().nth(njob).filter(|p| p.exists()) { if job.is_running() { eprintln!("ion: bg: job {} is already running", njob); false @@ -140,7 +138,7 @@ pub fn bg(shell: &mut Shell, args: &[small::String]) -> i32 { } } else { for arg in args { - if let Ok(njob) = arg.parse::<u32>() { + if let Ok(njob) = arg.parse::<usize>() { if !bg_job(shell, njob) { return FAILURE; } diff --git a/src/lib/shell/mod.rs b/src/lib/shell/mod.rs index 83de75a9..1856e7ba 100644 --- a/src/lib/shell/mod.rs +++ b/src/lib/shell/mod.rs @@ -89,7 +89,7 @@ pub struct Shell<'a> { /// here. previous_status: i32, /// The job ID of the previous command sent to the background. - previous_job: u32, + previous_job: usize, /// Contains all the options relative to the shell opts: ShellOptions, /// Contains information on all of the active background processes that are being managed @@ -381,7 +381,7 @@ impl<'a> Shell<'a> { exit_status } - pub fn previous_job(&self) -> Option<u32> { + pub fn previous_job(&self) -> Option<usize> { if self.previous_job == !0 { None } else { diff --git a/src/lib/shell/pipe_exec/job_control.rs b/src/lib/shell/pipe_exec/job_control.rs index be990ef7..f1f873d6 100644 --- a/src/lib/shell/pipe_exec/job_control.rs +++ b/src/lib/shell/pipe_exec/job_control.rs @@ -8,7 +8,7 @@ use crate::sys::{ }; use std::{ fmt, process, - sync::{Arc, Mutex}, + sync::Mutex, thread::{sleep, spawn}, time::Duration, }; @@ -81,44 +81,40 @@ impl<'a> Shell<'a> { } } - fn add_to_background( - processes: &Arc<Mutex<Vec<BackgroundProcess>>>, - job: BackgroundProcess, - ) -> u32 { - let mut processes = processes.lock().unwrap(); - match (*processes).iter().position(|x| !x.exists()) { + fn add_to_background(&mut self, job: BackgroundProcess) -> usize { + let mut processes = self.background_jobs_mut(); + match processes.iter().position(|x| !x.exists()) { Some(id) => { - (*processes)[id] = job; - id as u32 + processes[id] = job; + id } None => { - let njobs = (*processes).len(); - (*processes).push(job); - njobs as u32 + let njobs = processes.len(); + processes.push(job); + njobs } } } fn watch_background( - fg: &Arc<ForegroundSignals>, - processes: &Arc<Mutex<Vec<BackgroundProcess>>>, + fg: &ForegroundSignals, + processes: &Mutex<Vec<BackgroundProcess>>, pgid: u32, njob: usize, ) { - let (mut fg_was_grabbed, mut status); let mut exit_status = 0; macro_rules! get_process { (| $ident:ident | $func:expr) => { let mut processes = processes.lock().unwrap(); - let $ident = &mut processes.iter_mut().nth(njob).unwrap(); + let $ident = &mut processes.get_mut(njob).unwrap(); $func }; } loop { - fg_was_grabbed = fg.was_grabbed(pgid); - status = 0; + let fg_was_grabbed = fg.was_grabbed(pgid); + let mut status = 0; match waitpid(-(pgid as i32), &mut status, OPTS) { Err(errno) if errno == ECHILD => { if !fg_was_grabbed { @@ -126,7 +122,7 @@ impl<'a> Shell<'a> { } get_process!(|process| { - process.state = ProcessState::Empty; + process.forget(); if fg_was_grabbed { fg.reply_with(exit_status as i8); } @@ -138,7 +134,7 @@ impl<'a> Shell<'a> { eprintln!("ion: ([{}] {}) errored: {}", njob, pgid, errno); get_process!(|process| { - process.state = ProcessState::Empty; + process.forget(); if fg_was_grabbed { fg.errored(); } @@ -174,18 +170,17 @@ impl<'a> Shell<'a> { } pub fn send_to_background(&mut self, process: BackgroundProcess) { - // Increment the `Arc` counters so that these fields can be moved into - // the upcoming background thread. - let processes = self.background.clone(); - let fg_signals = self.foreground_signals.clone(); - // Add the process to the background list, and mark the job's ID as // the previous job in the shell (in case fg/bg is executed w/ no args). let pid = process.pid(); - let njob = Self::add_to_background(&processes, process); + let njob = self.add_to_background(process); self.previous_job = njob; eprintln!("ion: bg [{}] {}", njob, pid); + // Increment the `Arc` counters so that these fields can be moved into + // the upcoming background thread. + let processes = self.background.clone(); + let fg_signals = self.foreground_signals.clone(); // Spawn a background thread that will monitor the progress of the // background process, updating it's state changes until it finally // exits. @@ -194,27 +189,17 @@ impl<'a> Shell<'a> { /// Send a kill signal to all running background tasks. pub fn background_send(&self, signal: i32) { - if signal == sys::SIGHUP { - for process in self.background.lock().unwrap().iter() { - if !process.ignore_sighup { - let _ = sys::killpg(process.pid, signal); - } - } - } else { - for process in self.background.lock().unwrap().iter() { - if let ProcessState::Running = process.state { - let _ = sys::killpg(process.pid, signal); - } - } - } + let filter: fn(&&BackgroundProcess) -> bool = + if signal == sys::SIGHUP { |p| !p.ignore_sighup } else { |p| p.is_running() }; + self.background.lock().unwrap().iter().filter(filter).for_each(|p| { + let _ = sys::killpg(p.pid(), signal); + }) } /// Resumes all stopped background jobs pub fn resume_stopped(&mut self) { - for process in self.background.lock().unwrap().iter() { - if process.state == ProcessState::Stopped { - signals::resume(process.pid); - } + for process in self.background_jobs().iter().filter(|p| p.state == ProcessState::Stopped) { + signals::resume(process.pid()); } } -- GitLab