Merge pull request #2721 from ludovic-henry/fix-mono_ms_ticks
[mono.git] / mono / io-layer / processes.c
index 7e21445761a83f1a3a1741ff878eb5a3bd79f830..913f0b8af4b43604a528192492512caff7fac786 100644 (file)
@@ -6,6 +6,7 @@
  *
  * (C) 2002-2011 Novell, Inc.
  * Copyright 2011 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include <config.h>
@@ -1286,7 +1287,8 @@ GetExitCodeProcess (gpointer process, guint32 *code)
                        *code = STILL_ACTIVE;
                        return TRUE;
                } else {
-                       return FALSE;
+                       *code = -1;
+                       return TRUE;
                }
        }
 
@@ -2725,8 +2727,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
        WapiHandle_process *process_handle;
        pid_t pid G_GNUC_UNUSED, ret;
        int status;
-       guint32 start;
-       guint32 now;
+       gint64 start, now;
        struct MonoProcess *mp;
 
        /* FIXME: We can now easily wait on processes that aren't our own children,
@@ -2754,7 +2755,34 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
        /* We don't need to lock mono_processes here, the entry
         * has a handle_count > 0 which means it will not be freed. */
        mp = process_handle->mono_process;
-       g_assert (mp);
+       if (!mp) {
+               pid_t res;
+
+               if (pid == mono_process_current_pid ()) {
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
+                       return WAIT_TIMEOUT;
+               }
+
+               /* This path is used when calling Process.HasExited, so
+                * it is only used to poll the state of the process, not
+                * to actually wait on it to exit */
+               g_assert (timeout == 0);
+
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
+
+               res = waitpid (pid, &status, WNOHANG);
+               if (res == 0) {
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_TIMEOUT", __func__, handle, timeout);
+                       return WAIT_TIMEOUT;
+               }
+               if (res > 0) {
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
+                       return WAIT_OBJECT_0;
+               }
+
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process WAIT_FAILED, error : %s (%d))", __func__, handle, timeout, g_strerror (errno), errno);
+               return WAIT_FAILED;
+       }
 
        start = mono_msec_ticks ();
        now = start;