From ade6e0d421f0c2c642eb803e44b34cbf7efa7feb Mon Sep 17 00:00:00 2001
From: Ian Douglas Scott <ian@iandouglasscott.com>
Date: Sun, 6 Aug 2017 12:08:50 -0700
Subject: [PATCH] Prevent freezing due to double locking

---
 src/syscall/process.rs | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/src/syscall/process.rs b/src/syscall/process.rs
index 6582705e..fe87701d 100644
--- a/src/syscall/process.rs
+++ b/src/syscall/process.rs
@@ -601,7 +601,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
                 drop(path); // Drop so that usage is not allowed after unmapping context
                 drop(arg_ptrs); // Drop so that usage is not allowed after unmapping context
 
-                let (vfork, ppid) = {
+                let (vfork, ppid, files) = {
                     let contexts = context::contexts();
                     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
                     let mut context = context_lock.write();
@@ -773,21 +773,23 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
                     let vfork = context.vfork;
                     context.vfork = false;
 
-                    for (fd, file_option) in context.files.lock().iter_mut().enumerate() {
-                        let mut cloexec = false;
-                        if let Some(ref file) = *file_option {
-                            if file.cloexec {
-                                cloexec = true;
-                            }
-                        }
+                    let files = Arc::clone(&context.files);
+
+                    (vfork, context.ppid, files)
+                };
 
-                        if cloexec {
-                            let _ = file_option.take().unwrap().close(FileHandle::from(fd));
+                for (fd, file_option) in files.lock().iter_mut().enumerate() {
+                    let mut cloexec = false;
+                    if let Some(ref file) = *file_option {
+                        if file.cloexec {
+                            cloexec = true;
                         }
                     }
 
-                    (vfork, context.ppid)
-                };
+                    if cloexec {
+                        let _ = file_option.take().unwrap().close(FileHandle::from(fd));
+                    }
+                }
 
                 if vfork {
                     let contexts = context::contexts();
-- 
GitLab