diff --git a/src/lib/builtins/job_control.rs b/src/lib/builtins/job_control.rs
index ed93cff358a9618b3f8cb94d85e72d71a7618c48..7ea8a41a1e774ad3cb62a1fc3cd9727081fb6bb3 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 83de75a9791f274569e2cfb1cc81b856285d830f..1856e7bae342f63328692f3ceef9f8fb3a4cf2ca 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 be990ef7ed9919ba9e92a09da8ed996edff4d6bf..f1f873d6105d78cfd21af0231414f8fb974d4105 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());
         }
     }