[process] Fix Process.GetProcessesByName (#4351)
authorLudovic Henry <ludovic@xamarin.com>
Thu, 9 Feb 2017 03:29:03 +0000 (22:29 -0500)
committerGitHub <noreply@github.com>
Thu, 9 Feb 2017 03:29:03 +0000 (22:29 -0500)
To get a process by name, we need to access the other process ProcessName, but it can fails on non-win32 platforms. This failure wouldn't be caught in the referencesource implementation trigerring this bug.

The exception we would observe would be:
 Unhandled Exception:
 System.InvalidOperationException: Process has exited, so the requested information is not available.
   at System.Diagnostics.Process.get_ProcessName () [0x0002d] in /Users/alexander/dev/mono/mcs/class/System/System.Diagnostics/Process.cs:336
   at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ProcessName ()
   at Program.Main (System.String[] args) [0x0003b] in <9c838a66cdc44c81b38c974edcc9c029>:0
 [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Process has exited, so the requested information is not available.
   at System.Diagnostics.Process.get_ProcessName () [0x0002d] in /Users/alexander/dev/mono/mcs/class/System/System.Diagnostics/Process.cs:336
   at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:get_ProcessName ()
   at Program.Main (System.String[] args) [0x0003b] in <9c838a66cdc44c81b38c974edcc9c029>:0

Fixes bug https://bugzilla.xamarin.com/show_bug.cgi?id=52345

mcs/class/System/System.Diagnostics/Process.cs
mcs/class/System/Test/System.Diagnostics/ProcessTest.cs
mcs/class/referencesource/System/services/monitoring/system/diagnosticts/Process.cs

index 26a5c1ba93daabd7080b7d03f3bb283cf9a8e9c2..8423659fdc7cd86f9fd552b6656e3a49396cc0f1 100644 (file)
@@ -485,6 +485,34 @@ namespace System.Diagnostics
                        return (new Process (new SafeProcessHandle (proc, false), processId));
                }
 
+               public static Process[] GetProcessesByName(string processName, string machineName)
+               {
+                       if (machineName == null)
+                               throw new ArgumentNullException ("machineName");
+
+                       if (!IsLocalMachine (machineName))
+                               throw new NotImplementedException ();
+
+                       Process[] processes = GetProcesses ();
+                       if (processes.Length == 0)
+                               return processes;
+
+                       int size = 0;
+
+                       for (int i = 0; i < processes.Length; i++) {
+                               try {
+                                       if (String.Compare (processName, processes[i].ProcessName, true) == 0)
+                                               processes [size++] = processes[i];
+                               } catch (SystemException) {
+                                       /* The process might exit between GetProcesses_internal and GetProcessById */
+                               }
+                       }
+
+                       Array.Resize<Process> (ref processes, size);
+
+                       return processes;
+               }
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static int[] GetProcesses_internal();
 
index 20a93a732b6f1d1c3dc00368a5e0e0bc846db7c9..ac07fdc8bab5cfb132beb28b8ede2f3a76dd832b 100644 (file)
@@ -1113,5 +1113,12 @@ namespace MonoTests.System.Diagnostics
                        }
                }
 #endif // MONO_FEATURE_PROCESS_START
+
+               [Test]
+               public void GetProcessesByName()
+               {
+                       // This should return Process[0] or a Process[] with all the "foo" programs running
+                       Process.GetProcessesByName ("foo");
+               }
        }
 }
index 7c5307fa15513fe46d8c285a36e66b61d73225d7..2a5432d0ace9a56eb12090ae1f3b0aae7274756e 100644 (file)
@@ -1646,6 +1646,7 @@ namespace System.Diagnostics {
             return GetProcessesByName(processName, ".");
         }
 
+#if !MONO
         /// <devdoc>
         ///    <para>
         ///       Creates an array of <see cref='System.Diagnostics.Process'/> components that are associated with process resources on a
@@ -1671,6 +1672,7 @@ namespace System.Diagnostics {
             list.CopyTo(temp, 0);
             return temp;
         }
+#endif
 
         /// <devdoc>
         ///    <para>