From: Niklas Therning Date: Mon, 22 Aug 2016 14:54:03 +0000 (+0200) Subject: Fixes a handle leak in DirectoryInfo.EnumerateFileSystemInfos() X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=b8c33e6549bd8c6d36cc410d5fbcbe4ca343834c;p=mono.git Fixes a handle leak in DirectoryInfo.EnumerateFileSystemInfos() When running DirectoryInfo.EnumerateFileSystemInfos() on an empty directory MonoIO.FindFirst() will return null and the method returns without closing the handle which is opened by FindFirst(). This patch makes sure the finally block which closes the handle is run even when FindFirst() returns null. Also added a call to FindClose() and some more cleanup in the native implementation of MonoIO.FindFirst() when an allocation fails. This bug caused an exception in DirectyoryInfoTest.TearDown() and several other TearDown() methods in the MonoTests.System.IO tests on Windows due to RemoveDirectory() failing on an empty directory which still had an open handle associated with it. --- diff --git a/mcs/class/corlib/System.IO/DirectoryInfo.cs b/mcs/class/corlib/System.IO/DirectoryInfo.cs index d25432dcacd..205fadc0026 100644 --- a/mcs/class/corlib/System.IO/DirectoryInfo.cs +++ b/mcs/class/corlib/System.IO/DirectoryInfo.cs @@ -427,20 +427,20 @@ namespace System.IO { static internal IEnumerable EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption) { string path_with_pattern = Path.Combine (full, searchPattern); - IntPtr handle; + IntPtr handle = IntPtr.Zero; MonoIOError error; FileAttributes rattr; bool subdirs = searchOption == SearchOption.AllDirectories; Path.Validate (full); - string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle); - if (s == null) - yield break; - if (error != 0) - throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); - try { + string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle); + if (s == null) + yield break; + if (error != 0) + throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); + do { if (((rattr & FileAttributes.ReparsePoint) == 0)){ if ((rattr & FileAttributes.Directory) != 0) @@ -455,7 +455,8 @@ namespace System.IO { } while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null); } finally { - MonoIO.FindClose (handle); + if (handle != IntPtr.Zero) + MonoIO.FindClose (handle); } } diff --git a/mono/metadata/file-io.c b/mono/metadata/file-io.c index 9315bdf828f..be1ad8a1c79 100644 --- a/mono/metadata/file-io.c +++ b/mono/metadata/file-io.c @@ -489,8 +489,13 @@ ves_icall_System_IO_MonoIO_FindFirst (MonoString *path, ifh = g_new (IncrementalFind, 1); ifh->find_handle = find_handle; ifh->utf8_path = mono_string_to_utf8_checked (path, &error); - if (mono_error_set_pending_exception (&error)) + if (mono_error_set_pending_exception (&error)) { + MONO_ENTER_GC_SAFE; + FindClose (find_handle); + MONO_EXIT_GC_SAFE; + g_free (ifh); return NULL; + } ifh->domain = mono_domain_get (); *handle = ifh;