Merge pull request #2802 from BrzVlad/feature-evacuation-opt2
[mono.git] / mono / io-layer / processes.c
index 720705d2aab42d9ba546153427a8a465af176f27..7e46c31ba3e1564a9323022f9a0e3542b5f71fca 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>
@@ -97,6 +98,7 @@
 #include <mono/io-layer/handles-private.h>
 #include <mono/io-layer/process-private.h>
 #include <mono/io-layer/threads.h>
+#include <mono/io-layer/io-trace.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-path.h>
 #include <mono/io-layer/timefuncs-private.h>
 #include <mono/utils/mono-signal-handler.h>
 #include <mono/utils/mono-proclib.h>
 #include <mono/utils/mono-once.h>
+#include <mono/utils/mono-logger-internals.h>
 
 /* The process' environment strings */
 #if defined(__APPLE__)
@@ -124,13 +127,6 @@ static char *mono_environ[1] = { NULL };
 extern char **environ;
 #endif
 
-#if 0
-#define DEBUG(...) g_message(__VA_ARGS__)
-#define DEBUG_ENABLED 1
-#else
-#define DEBUG(...)
-#endif
-
 static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertable);
 static void process_close (gpointer handle, gpointer data);
 static gboolean is_pid_valid (pid_t pid);
@@ -576,11 +572,11 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        char *dir = NULL, **env_strings = NULL, **argv = NULL;
        guint32 i, env_count = 0;
        gboolean ret = FALSE;
-       gpointer handle;
+       gpointer handle = NULL;
        WapiHandle_process process_handle = {0}, *process_handle_data;
        GError *gerr = NULL;
        int in_fd, out_fd, err_fd;
-       pid_t pid;
+       pid_t pid = 0;
        int thr_ret;
        int startup_pipe [2] = {-1, -1};
        int dummy;
@@ -618,7 +614,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        if (appname != NULL) {
                cmd = mono_unicode_to_external (appname);
                if (cmd == NULL) {
-                       DEBUG ("%s: unicode conversion returned NULL",
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
                                   __func__);
 
                        SetLastError (ERROR_PATH_NOT_FOUND);
@@ -631,7 +627,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        if (cmdline != NULL) {
                args = mono_unicode_to_external (cmdline);
                if (args == NULL) {
-                       DEBUG ("%s: unicode conversion returned NULL", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                        SetLastError (ERROR_PATH_NOT_FOUND);
                        goto free_strings;
@@ -641,7 +637,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
        if (cwd != NULL) {
                dir = mono_unicode_to_external (cwd);
                if (dir == NULL) {
-                       DEBUG ("%s: unicode conversion returned NULL", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
 
                        SetLastError (ERROR_PATH_NOT_FOUND);
                        goto free_strings;
@@ -671,7 +667,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
 
                        /* Executable existing ? */
                        if (!is_readable_or_executable (prog)) {
-                               DEBUG ("%s: Couldn't find executable %s",
+                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
                                           __func__, prog);
                                g_free (unquoted);
                                SetLastError (ERROR_FILE_NOT_FOUND);
@@ -688,7 +684,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
 
                        /* And make sure it's readable */
                        if (!is_readable_or_executable (prog)) {
-                               DEBUG ("%s: Couldn't find executable %s",
+                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
                                           __func__, prog);
                                g_free (unquoted);
                                SetLastError (ERROR_FILE_NOT_FOUND);
@@ -753,7 +749,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                
                if (token == NULL) {
                        /* Give up */
-                       DEBUG ("%s: Couldn't find what to exec", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
 
                        SetLastError (ERROR_PATH_NOT_FOUND);
                        goto free_strings;
@@ -779,7 +775,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        
                        /* Executable existing ? */
                        if (!is_readable_or_executable (prog)) {
-                               DEBUG ("%s: Couldn't find executable %s",
+                               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
                                           __func__, token);
                                g_free (token);
                                SetLastError (ERROR_FILE_NOT_FOUND);
@@ -806,7 +802,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                                g_free (prog);
                                prog = g_find_program_in_path (token);
                                if (prog == NULL) {
-                                       DEBUG ("%s: Couldn't find executable %s", __func__, token);
+                                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
 
                                        g_free (token);
                                        SetLastError (ERROR_FILE_NOT_FOUND);
@@ -818,7 +814,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                g_free (token);
        }
 
-       DEBUG ("%s: Exec prog [%s] args [%s]", __func__, prog,
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Exec prog [%s] args [%s]", __func__, prog,
                   args_after_prog);
        
        /* Check for CLR binaries; if found, we will try to invoke
@@ -861,7 +857,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                }
        } else {
                if (!is_executable (prog)) {
-                       DEBUG ("%s: Executable permisson not set on %s", __func__, prog);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
                        SetLastError (ERROR_ACCESS_DENIED);
                        goto free_strings;
                }
@@ -972,7 +968,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                /* Could not create the pipe to synchroniz process startup. We'll just not synchronize.
                 * This is just for a very hard to hit race condition in the first place */
                startup_pipe [0] = startup_pipe [1] = -1;
-               DEBUG ("%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: new process startup not synchronized. We may not notice if the newly created process exits immediately.", __func__);
        }
 
        thr_ret = _wapi_handle_lock_shared_handles ();
@@ -991,7 +987,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                if (startup_pipe [0] != -1) {
                        /* Wait until the parent has updated it's internal data */
                        ssize_t _i G_GNUC_UNUSED = read (startup_pipe [0], &dummy, 1);
-                       DEBUG ("%s: child: parent has completed its setup", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: child: parent has completed its setup", __func__);
                        close (startup_pipe [0]);
                        close (startup_pipe [1]);
                }
@@ -1012,7 +1008,7 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
                        close (i);
 
 #ifdef DEBUG_ENABLED
-               DEBUG ("%s: exec()ing [%s] in dir [%s]", __func__, cmd,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: exec()ing [%s] in dir [%s]", __func__, cmd,
                           dir == NULL?".":dir);
                for (i = 0; argv[i] != NULL; i++)
                        g_message ("arg %d: [%s]", i, argv[i]);
@@ -1109,8 +1105,7 @@ free_strings:
        if (argv)
                g_strfreev (argv);
        
-       DEBUG ("%s: returning handle %p for pid %d", __func__, handle,
-                  pid);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p for pid %d", __func__, handle, pid);
 
        /* Check if something needs to be cleaned up. */
        mono_processes_cleanup ();
@@ -1130,7 +1125,7 @@ process_set_name (WapiHandle_process *process_handle)
        progname = g_get_prgname ();
        utf8_progname = mono_utf8_from_external (progname);
 
-       DEBUG ("%s: using [%s] as prog name", __func__, progname);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: using [%s] as prog name", __func__, progname);
 
        if (utf8_progname) {
                slash = strrchr (utf8_progname, '/');
@@ -1208,7 +1203,7 @@ process_open_compare (gpointer handle, gpointer user_data)
        process_handle = lookup_process_handle (handle);
        g_assert (process_handle);
        
-       DEBUG ("%s: looking at process %d", __func__, process_handle->id);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->id);
 
        checking_pid = process_handle->id;
 
@@ -1250,7 +1245,7 @@ OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, g
        /* Find the process handle that corresponds to pid */
        gpointer handle = NULL;
        
-       DEBUG ("%s: looking for process %d", __func__, pid);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for process %d", __func__, pid);
 
        handle = _wapi_search_handle (WAPI_HANDLE_PROCESS,
                                      process_open_compare,
@@ -1262,7 +1257,7 @@ OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, g
                         */
                        return WAPI_PID_TO_HANDLE (pid);
                } else {
-                       DEBUG ("%s: Can't find pid %d", __func__, pid);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
 
                        SetLastError (ERROR_PROC_NOT_FOUND);
        
@@ -1298,7 +1293,7 @@ GetExitCodeProcess (gpointer process, guint32 *code)
 
        process_handle = lookup_process_handle (process);
        if (!process_handle) {
-               DEBUG ("%s: Can't find process %p", __func__, process);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                
                return FALSE;
        }
@@ -1352,7 +1347,7 @@ GetProcessTimes (gpointer process, WapiFileTime *create_time,
 
        process_handle = lookup_process_handle (process);
        if (!process_handle) {
-               DEBUG ("%s: Can't find process %p", __func__, process);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                
                return FALSE;
        }
@@ -1517,7 +1512,7 @@ static GSList *load_modules (void)
                mod->inode = i;
                mod->filename = g_strdup (info->dlpi_name); 
 
-               DEBUG ("%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__,
                                   mod->inode, mod->filename, mod->address_start, mod->address_end);
 
                free(info);
@@ -1698,7 +1693,7 @@ static gboolean match_procname_to_modulename (char *procname, char *modulename)
        if (procname == NULL || modulename == NULL)
                return (FALSE);
 
-       DEBUG ("%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: procname=\"%s\", modulename=\"%s\"", __func__, procname, modulename);
        pname = mono_path_resolve_symlinks (procname);
        mname = mono_path_resolve_symlinks (modulename);
 
@@ -1727,7 +1722,7 @@ static gboolean match_procname_to_modulename (char *procname, char *modulename)
        g_free (pname);
        g_free (mname);
 
-       DEBUG ("%s: result is %d", __func__, result);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: result is %d", __func__, result);
        return result;
 }
 
@@ -1788,7 +1783,7 @@ gboolean EnumProcessModules (gpointer process, gpointer *modules,
        } else {
                process_handle = lookup_process_handle (process);
                if (!process_handle) {
-                       DEBUG ("%s: Can't find process %p", __func__, process);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                
                        return FALSE;
                }
@@ -1925,7 +1920,7 @@ get_process_name_from_proc (pid_t pid)
        if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
                if (errno == ENOMEM) {
                        free(pi);
-                       DEBUG ("%s: Didn't allocate enough memory for kproc info", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
                }
                return(ret);
        }
@@ -1942,7 +1937,7 @@ get_process_name_from_proc (pid_t pid)
        mib [2] = KERN_PROC_PID;
        mib [3] = pid;
        if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
-               DEBUG ("%s: sysctl() failed: %d", __func__, errno);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
                return(ret);
        }
 
@@ -1952,7 +1947,7 @@ get_process_name_from_proc (pid_t pid)
        if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
                if (errno == ENOMEM) {
                        free(pi);
-                       DEBUG ("%s: Didn't allocate enough memory for kproc info", __func__);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
                }
                return(ret);
        }
@@ -1970,7 +1965,7 @@ get_process_name_from_proc (pid_t pid)
 
 retry:
        if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
-               DEBUG ("%s: sysctl() failed: %d", __func__, errno);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sysctl() failed: %d", __func__, errno);
                return(ret);
        }
 
@@ -2106,7 +2101,7 @@ get_module_name (gpointer process, gpointer module,
        int i;
        char *proc_name = NULL;
        
-       DEBUG ("%s: Getting module base name, process handle %p module %p",
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
                   __func__, process, module);
 
        size = size * sizeof (gunichar2); /* adjust for unicode characters */
@@ -2121,7 +2116,7 @@ get_module_name (gpointer process, gpointer module,
        } else {
                process_handle = lookup_process_handle (process);
                if (!process_handle) {
-                       DEBUG ("%s: Can't find process %p", __func__,
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
                                   process);
                        
                        return 0;
@@ -2182,7 +2177,7 @@ get_module_name (gpointer process, gpointer module,
        g_free (proc_name);
 
        if (procname_ext) {
-               DEBUG ("%s: Process name is [%s]", __func__,
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
                           procname_ext);
 
                procname = mono_unicode_from_external (procname_ext, &bytes);
@@ -2198,11 +2193,11 @@ get_module_name (gpointer process, gpointer module,
                bytes += 2;
                
                if (size < bytes) {
-                       DEBUG ("%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
 
                        memcpy (basename, procname, size);
                } else {
-                       DEBUG ("%s: Size %d larger than needed (%ld)",
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
                                   __func__, size, bytes);
 
                        memcpy (basename, procname, bytes);
@@ -2249,11 +2244,11 @@ get_module_filename (gpointer process, gpointer module,
        bytes += 2;
 
        if (size < bytes) {
-               DEBUG ("%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d smaller than needed (%ld); truncating", __func__, size, bytes);
 
                memcpy (basename, proc_path, size);
        } else {
-               DEBUG ("%s: Size %d larger than needed (%ld)",
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Size %d larger than needed (%ld)",
                           __func__, size, bytes);
 
                memcpy (basename, proc_path, bytes);
@@ -2294,7 +2289,7 @@ GetModuleInformation (gpointer process, gpointer module,
        gboolean ret = FALSE;
        char *proc_name = NULL;
        
-       DEBUG ("%s: Getting module info, process handle %p module %p",
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
                   __func__, process, module);
 
        if (modinfo == NULL || size < sizeof (WapiModuleInfo))
@@ -2306,7 +2301,7 @@ GetModuleInformation (gpointer process, gpointer module,
        } else {
                process_handle = lookup_process_handle (process);
                if (!process_handle) {
-                       DEBUG ("%s: Can't find process %p", __func__,
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__,
                                   process);
                        
                        return FALSE;
@@ -2370,7 +2365,7 @@ GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
        
        process_handle = lookup_process_handle (process);
        if (!process_handle) {
-               DEBUG ("%s: Can't find process %p", __func__, process);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                
                return FALSE;
        }
@@ -2393,7 +2388,7 @@ SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
 
        process_handle = lookup_process_handle (process);
        if (!process_handle) {
-               DEBUG ("%s: Can't find process %p", __func__, process);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                
                return FALSE;
        }
@@ -2420,7 +2415,7 @@ TerminateProcess (gpointer process, gint32 exitCode)
        } else {
                process_handle = lookup_process_handle (process);
                if (!process_handle) {
-                       DEBUG ("%s: Can't find process %p", __func__, process);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@ -2585,7 +2580,7 @@ mono_processes_cleanup (void)
        GSList *l;
        gpointer unref_handle;
 
-       DEBUG ("%s", __func__);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
 
        /* Ensure we're not in here in multiple threads at once, nor recursive. */
        if (InterlockedCompareExchange (&mono_processes_cleaning_up, 1, 0) != 0)
@@ -2649,7 +2644,7 @@ mono_processes_cleanup (void)
 
        mono_os_mutex_unlock (&mono_processes_mutex);
 
-       DEBUG ("%s done", __func__);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s done", __func__);
 
        InterlockedDecrement (&mono_processes_cleaning_up);
 }
@@ -2659,7 +2654,7 @@ process_close (gpointer handle, gpointer data)
 {
        WapiHandle_process *process_handle;
 
-       DEBUG ("%s", __func__);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
 
        process_handle = (WapiHandle_process *) data;
        g_free (process_handle->proc_name);
@@ -2676,7 +2671,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
        int pid;
        struct MonoProcess *p;
 
-       DEBUG ("SIG CHILD handler for pid: %i\n", info->si_pid);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "SIG CHILD handler for pid: %i\n", info->si_pid);
 
        do {
                do {
@@ -2686,7 +2681,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
                if (pid <= 0)
                        break;
 
-               DEBUG ("child ended: %i", pid);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "child ended: %i", pid);
 
                /*
                 * This can run concurrently with the code in the rest of this module.
@@ -2706,7 +2701,7 @@ MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, sigi
                }
        } while (1);
 
-       DEBUG ("SIG CHILD handler: done looping.");
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "SIG CHILD handler: done looping.");
 }
 
 #endif
@@ -2721,7 +2716,7 @@ process_add_sigchld_handler (void)
        sigemptyset (&sa.sa_mask);
        sa.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
        g_assert (sigaction (SIGCHLD, &sa, &previous_chld_sa) != -1);
-       DEBUG ("Added SIGCHLD handler");
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "Added SIGCHLD handler");
 #endif
 }
 
@@ -2739,7 +2734,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
         * but WaitFor*Object won't call us for pseudo handles. */
        g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
 
-       DEBUG ("%s (%p, %u)", __func__, handle, timeout);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
 
        process_handle = lookup_process_handle (handle);
        if (!process_handle) {
@@ -2749,35 +2744,62 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
 
        if (process_handle->exited) {
                /* We've already done this one */
-               DEBUG ("%s (%p, %u): Process already exited", __func__, handle, timeout);
+               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Process already exited", __func__, handle, timeout);
                return WAIT_OBJECT_0;
        }
 
        pid = process_handle->id;
 
-       DEBUG ("%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
 
        /* 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;
 
        while (1) {
                if (timeout != INFINITE) {
-                       DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", 
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...", 
                                   __func__, handle, timeout, (timeout - (now - start)));
                        ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alertable ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
                } else {
-                       DEBUG ("%s (%p, %u): waiting on semaphore forever...", 
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore forever...", 
                                   __func__, handle, timeout);
                        ret = mono_os_sem_wait (&mp->exit_sem, alertable ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
                }
 
                if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
-                       DEBUG ("%s (%p, %u): sem_timedwait failure: %s", 
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): sem_timedwait failure: %s", 
                                   __func__, handle, timeout, g_strerror (errno));
                        /* Should we return a failure here? */
                }
@@ -2789,24 +2811,24 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
                }
 
                if (timeout == 0) {
-                       DEBUG ("%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT (timeout = 0)", __func__, handle, timeout);
                        return WAIT_TIMEOUT;
                }
 
                now = mono_msec_ticks ();
                if (now - start >= timeout) {
-                       DEBUG ("%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
                        return WAIT_TIMEOUT;
                }
                
                if (alertable && _wapi_thread_cur_apc_pending ()) {
-                       DEBUG ("%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
+                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
                        return WAIT_IO_COMPLETION;
                }
        }
 
        /* Process must have exited */
-       DEBUG ("%s (%p, %u): Waited successfully", __func__, handle, timeout);
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
 
        ret = _wapi_handle_lock_shared_handles ();
        g_assert (ret == 0);
@@ -2820,7 +2842,7 @@ process_wait (gpointer handle, guint32 timeout, gboolean alertable)
 
        process_handle->exited = TRUE;
 
-       DEBUG ("%s (%p, %u): Setting pid %d signalled, exit status %d",
+       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Setting pid %d signalled, exit status %d",
                   __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
 
        _wapi_handle_set_signal_state (handle, TRUE, TRUE);