[Lldb-commits] [lldb] r228130 - Avoid leakage of file descriptors in LLDB and LLGS

Pavel Labath labath at google.com
Wed Feb 4 02:36:58 PST 2015


Author: labath
Date: Wed Feb  4 04:36:57 2015
New Revision: 228130

URL: http://llvm.org/viewvc/llvm-project?rev=228130&view=rev
Log:
Avoid leakage of file descriptors in LLDB and LLGS

Summary:
Both LLDB and LLGS are leaking file descriptors into the debugged process. This plugs the leak by
closing the unneeded descriptors. In one case I use O_CLOEXEC, which I hope is supported on
relevant platforms. I also added a regression test and plugged a fd leak in dosep.py.

Reviewers: vharron, clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D7372

Added:
    lldb/trunk/test/functionalities/avoids-fd-leak/
    lldb/trunk/test/functionalities/avoids-fd-leak/Makefile
    lldb/trunk/test/functionalities/avoids-fd-leak/TestFdLeak.py
    lldb/trunk/test/functionalities/avoids-fd-leak/main.c
Modified:
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
    lldb/trunk/source/Target/ProcessLaunchInfo.cpp
    lldb/trunk/test/dosep.py

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=228130&r1=228129&r2=228130&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Wed Feb  4 04:36:57 2015
@@ -1545,6 +1545,11 @@ NativeProcessLinux::Launch(LaunchArgs *a
         if (args->m_error.Fail())
             exit(ePtraceFailed);
 
+        // terminal has already dupped the tty descriptors to stdin/out/err.
+        // This closes original fd from which they were copied (and avoids
+        // leaking descriptors to the debugged process.
+        terminal.CloseSlaveFileDescriptor();
+
         // Do not inherit setgid powers.
         if (setgid(getgid()) != 0)
             exit(eSetGidFailed);
@@ -3532,7 +3537,10 @@ NativeProcessLinux::DupDescriptor(const
     if (target_fd == -1)
         return false;
 
-    return (dup2(target_fd, fd) == -1) ? false : true;
+    if (dup2(target_fd, fd) == -1)
+        return false;
+
+    return (close(target_fd) == -1) ? false : true;
 }
 
 void

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=228130&r1=228129&r2=228130&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Wed Feb  4 04:36:57 2015
@@ -1356,6 +1356,11 @@ ProcessMonitor::Launch(LaunchArgs *args)
         if (PTRACE(PTRACE_TRACEME, 0, NULL, NULL, 0) < 0)
             exit(ePtraceFailed);
 
+        // terminal has already dupped the tty descriptors to stdin/out/err.
+        // This closes original fd from which they were copied (and avoids
+        // leaking descriptors to the debugged process.
+        terminal.CloseSlaveFileDescriptor();
+
         // Do not inherit setgid powers.
         if (setgid(getgid()) != 0)
             exit(eSetGidFailed);
@@ -2319,7 +2324,10 @@ ProcessMonitor::DupDescriptor(const char
     if (target_fd == -1)
         return false;
 
-    return (dup2(target_fd, fd) == -1) ? false : true;
+    if (dup2(target_fd, fd) == -1)
+        return false;
+
+    return (close(target_fd) == -1) ? false : true;
 }
 
 void

Modified: lldb/trunk/source/Target/ProcessLaunchInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ProcessLaunchInfo.cpp?rev=228130&r1=228129&r2=228130&view=diff
==============================================================================
--- lldb/trunk/source/Target/ProcessLaunchInfo.cpp (original)
+++ lldb/trunk/source/Target/ProcessLaunchInfo.cpp Wed Feb  4 04:36:57 2015
@@ -344,7 +344,7 @@ ProcessLaunchInfo::FinalizeFileActions (
                     log->Printf ("ProcessLaunchInfo::%s default_to_use_pty is set, and at least one stdin/stderr/stdout is unset, so generating a pty to use for it",
                                  __FUNCTION__);
 
-                if (m_pty->OpenFirstAvailableMaster(O_RDWR| O_NOCTTY, NULL, 0))
+                if (m_pty->OpenFirstAvailableMaster(O_RDWR | O_NOCTTY | O_CLOEXEC, NULL, 0))
                 {
                     const char *slave_path = m_pty->GetSlaveName(NULL, 0);
 

Modified: lldb/trunk/test/dosep.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/dosep.py?rev=228130&r1=228129&r2=228130&view=diff
==============================================================================
--- lldb/trunk/test/dosep.py (original)
+++ lldb/trunk/test/dosep.py Wed Feb  4 04:36:57 2015
@@ -57,8 +57,8 @@ def call_with_timeout(command, timeout):
     """Run command with a timeout if possible."""
     if timeout_command and timeout != "0":
         return subprocess.call([timeout_command, timeout] + command,
-                               stdin=subprocess.PIPE)
-    return (ePassed if subprocess.call(command, stdin=subprocess.PIPE) == 0
+                               stdin=subprocess.PIPE, close_fds=True)
+    return (ePassed if subprocess.call(command, stdin=subprocess.PIPE, close_fds=True) == 0
             else eFailed)
 
 def process_dir(root, files, test_root, dotest_options):

Added: lldb/trunk/test/functionalities/avoids-fd-leak/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/avoids-fd-leak/Makefile?rev=228130&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/avoids-fd-leak/Makefile (added)
+++ lldb/trunk/test/functionalities/avoids-fd-leak/Makefile Wed Feb  4 04:36:57 2015
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/avoids-fd-leak/TestFdLeak.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/avoids-fd-leak/TestFdLeak.py?rev=228130&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/avoids-fd-leak/TestFdLeak.py (added)
+++ lldb/trunk/test/functionalities/avoids-fd-leak/TestFdLeak.py Wed Feb  4 04:36:57 2015
@@ -0,0 +1,32 @@
+"""
+Test whether a process started by lldb has no extra file descriptors open.
+"""
+
+import os
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class AvoidsFdLeakTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @expectedFailureWindows("The check for descriptor leakage needs to be implemented differently")
+    def test_fd_leak (self):
+        self.buildDefault()
+        exe = os.path.join (os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+
+        process = target.LaunchSimple (None, None, self.get_process_working_directory())
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        self.assertTrue(process.GetState() == lldb.eStateExited)
+        self.assertTrue(process.GetExitStatus() == 0)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/avoids-fd-leak/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/avoids-fd-leak/main.c?rev=228130&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/avoids-fd-leak/main.c (added)
+++ lldb/trunk/test/functionalities/avoids-fd-leak/main.c Wed Feb  4 04:36:57 2015
@@ -0,0 +1,28 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+
+int
+main (int argc, char const **argv)
+{
+    struct stat buf;
+    int i;
+
+    // Make sure stdin/stdout/stderr exist.
+    for (i = 0; i <= 2; ++i) {
+        if (fstat(i, &buf) != 0)
+            return 1;
+    }
+
+    // Make sure no other file descriptors are open.
+    for (i = 3; i <= 256; ++i) {
+        if (fstat(i, &buf) == 0 || errno != EBADF) {
+            fprintf(stderr, "File descriptor %d is open.\n", i);
+            return 2;
+        }
+    }
+
+    return 0;
+}





More information about the lldb-commits mailing list