Avoid leaking log file descriptors into the inferior process.

Summary:
This commit adds a new open flag File::eOpenOptionCloseOnExec (i.e., O_CLOEXEC), and adds it to
the list of flags when opening log files (#ifndef windows). A regression test is included.

Reviewers: vharron, clayborg

Subscribers: lldb-commits

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

llvm-svn: 228310
This commit is contained in:
Pavel Labath 2015-02-05 16:44:42 +00:00
parent fe0c7ad852
commit 97a9ac1982
4 changed files with 22 additions and 6 deletions

View File

@ -42,7 +42,8 @@ public:
eOpenOptionNonBlocking = (1u << 4), // File reads
eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist
eOpenOptionCanCreateNewOnly = (1u << 6), // Can create file only if it doesn't already exist
eOpenoptionDontFollowSymlinks = (1u << 7)
eOpenoptionDontFollowSymlinks = (1u << 7),
eOpenOptionCloseOnExec = (1u << 8) // Close the file when executing a new process
};
static mode_t

View File

@ -49,7 +49,8 @@ StreamFile::StreamFile (FILE *fh, bool transfer_ownership) :
StreamFile::StreamFile (const char *path) :
Stream (),
m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, lldb::eFilePermissionsFileDefault)
m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec,
lldb::eFilePermissionsFileDefault)
{
}

View File

@ -288,6 +288,8 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
#ifndef _WIN32
if (options & eOpenOptionNonBlocking)
oflag |= O_NONBLOCK;
if (options & eOpenOptionCloseOnExec)
oflag |= O_CLOEXEC;
#else
oflag |= O_BINARY;
#endif

View File

@ -12,18 +12,30 @@ class AvoidsFdLeakTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@expectedFailureWindows("The check for descriptor leakage needs to be implemented differently")
def test_fd_leak (self):
@skipIfWindows # The check for descriptor leakage needs to be implemented differently here.
def test_fd_leak_basic (self):
self.do_test([])
@skipIfWindows # The check for descriptor leakage needs to be implemented differently here.
def test_fd_leak_log (self):
self.do_test(["log enable -f '/dev/null' lldb commands"])
def do_test (self, commands):
self.buildDefault()
exe = os.path.join (os.getcwd(), "a.out")
for c in commands:
self.runCmd(c)
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)
self.assertTrue(process.GetState() == lldb.eStateExited, "Process should have exited.")
self.assertTrue(process.GetExitStatus() == 0,
"Process returned non-zero status. Were incorrect file descriptors passed?")
if __name__ == '__main__':
import atexit