Merge pull request #946 from akoeplinger/fix-mono-parallel
[mono.git] / mono / io-layer / processes.c
index 0f14de7894fce414e3befcbc841a254429d0567d..afbe440448bf6553e0f535520bab3ae2e94cd0cc 100644 (file)
@@ -68,7 +68,6 @@
 #include <mono/io-layer/wapi-private.h>
 #include <mono/io-layer/handles-private.h>
 #include <mono/io-layer/misc-private.h>
-#include <mono/io-layer/mono-mutex.h>
 #include <mono/io-layer/process-private.h>
 #include <mono/io-layer/threads.h>
 #include <mono/utils/strenc.h>
@@ -76,6 +75,8 @@
 #include <mono/io-layer/timefuncs-private.h>
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-membar.h>
+#include <mono/utils/mono-mutex.h>
+#include <mono/utils/mono-signal-handler.h>
 
 /* The process' environment strings */
 #if defined(__APPLE__) && !defined (__arm__)
@@ -141,6 +142,7 @@ static void mono_processes_cleanup (void);
 
 static mono_once_t process_current_once=MONO_ONCE_INIT;
 static gpointer current_process=NULL;
+static char *cli_launcher;
 
 static mono_once_t process_ops_once=MONO_ONCE_INIT;
 
@@ -329,10 +331,7 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                        return FALSE;
 
 #ifdef PLATFORM_MACOSX
-               if (is_macos_10_5_or_higher ())
-                       handler = g_strdup ("/usr/bin/open -W");
-               else
-                       handler = g_strdup ("/usr/bin/open");
+               handler = g_strdup ("/usr/bin/open");
 #else
                /*
                 * On Linux, try: xdg-open, the FreeDesktop standard way of doing it,
@@ -382,6 +381,9 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
                                SetLastError (ERROR_INVALID_DATA);
                        return FALSE;
                }
+               /* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
+               CloseHandle (process_info.hProcess);
+               process_info.hProcess = NULL;
        }
        
        if (sei->fMask & SEE_MASK_NOCLOSEPROCESS) {
@@ -805,10 +807,13 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline,
         * them using the same mono binary that started us.
         */
        if (is_managed_binary (prog)) {
-               gunichar2 *newapp, *newcmd;
+               gunichar2 *newapp = NULL, *newcmd;
                gsize bytes_ignored;
 
-               newapp = mono_unicode_from_external ("mono", &bytes_ignored);
+               if (cli_launcher)
+                       newapp = mono_unicode_from_external (cli_launcher, &bytes_ignored);
+               else
+                       newapp = mono_unicode_from_external ("mono", &bytes_ignored);
 
                if (newapp != NULL) {
                        if (appname != NULL) {
@@ -1345,13 +1350,13 @@ gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
        gboolean done;
        size_t proclength, size;
 #if defined(__OpenBSD__)
-       struct kinfo_proc2 *result;
+       struct kinfo_proc *result;
        int name[6];
        name[0] = CTL_KERN;
-       name[1] = KERN_PROC2;
+       name[1] = KERN_PROC;
        name[2] = KERN_PROC_ALL;
        name[3] = 0;
-       name[4] = sizeof(struct kinfo_proc2);
+       name[4] = sizeof(struct kinfo_proc);
        name[5] = 0;
 #else
        struct kinfo_proc *result;
@@ -1379,15 +1384,17 @@ gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
                                return FALSE;
 
 #if defined(__OpenBSD__)
-                       name[5] = (int)(proclength / sizeof(struct kinfo_proc2));
+                       name[5] = (int)(proclength / sizeof(struct kinfo_proc));
 #endif
 
                        err = sysctl ((int *) name, size, result, &proclength, NULL, 0);
 
                        if (err == 0) 
                                done = TRUE;
-                       else
+                       else {
                                free (result);
+                               result = NULL;
+                       }
                }
        } while (err == 0 && !done);
        
@@ -1399,11 +1406,8 @@ gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
                return(FALSE);
        }       
 
-#if defined(__OpenBSD__)
-       count = proclength / sizeof(struct kinfo_proc2);
-#else
        count = proclength / sizeof(struct kinfo_proc);
-#endif
+
        fit = len / sizeof(guint32);
        for (i = 0, j = 0; j< fit && i < count; i++) {
 #if defined(__OpenBSD__)
@@ -1635,15 +1639,12 @@ gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
        if (process_handle->id == getpid ()) {
                struct rusage time_data;
                if (getrusage (RUSAGE_SELF, &time_data) == 0) {
-                       gint64 tick_val;
-                       gint64 *tick_val_ptr;
+                       guint64 tick_val;
                        ku_times_set = TRUE;
-                       tick_val = time_data.ru_utime.tv_sec * 10000000 + time_data.ru_utime.tv_usec * 10;
-                       tick_val_ptr = (gint64*)user_time;
-                       *tick_val_ptr = tick_val;
-                       tick_val = time_data.ru_stime.tv_sec * 10000000 + time_data.ru_stime.tv_usec * 10;
-                       tick_val_ptr = (gint64*)kernel_time;
-                       *tick_val_ptr = tick_val;
+                       tick_val = (guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10;
+                       _wapi_guint64_to_filetime (tick_val, user_time);
+                       tick_val = (guint64)time_data.ru_stime.tv_sec * 10000000 + (guint64)time_data.ru_stime.tv_usec * 10;
+                       _wapi_guint64_to_filetime (tick_val, kernel_time);
                }
        }
 #endif
@@ -1710,14 +1711,13 @@ static GSList *load_modules (void)
                const struct section *sec;
 #endif
                const char *name;
-               intptr_t slide;
 
-               slide = _dyld_get_image_vmaddr_slide (i);
                name = _dyld_get_image_name (i);
-               hdr = _dyld_get_image_header (i);
 #if SIZEOF_VOID_P == 8
+               hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
                sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
 #else
+               hdr = _dyld_get_image_header (i);
                sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
 #endif
 
@@ -2116,11 +2116,13 @@ static gchar *get_process_name_from_proc (pid_t pid)
 #if defined(__OpenBSD__)
        int mib [6];
        size_t size;
-       struct kinfo_proc2 *pi;
+       struct kinfo_proc *pi;
 #elif defined(PLATFORM_MACOSX)
+#if !(!defined (__mono_ppc__) && defined (TARGET_OSX))
        size_t size;
        struct kinfo_proc *pi;
        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+#endif
 #else
        FILE *fp;
        gchar *filename = NULL;
@@ -2171,10 +2173,10 @@ static gchar *get_process_name_from_proc (pid_t pid)
 #endif
 #elif defined(__OpenBSD__)
        mib [0] = CTL_KERN;
-       mib [1] = KERN_PROC2;
+       mib [1] = KERN_PROC;
        mib [2] = KERN_PROC_PID;
        mib [3] = pid;
-       mib [4] = sizeof(struct kinfo_proc2);
+       mib [4] = sizeof(struct kinfo_proc);
        mib [5] = 0;
 
 retry:
@@ -2184,10 +2186,10 @@ retry:
        if ((pi = malloc(size)) == NULL)
                return(ret);
 
-       mib[5] = (int)(size / sizeof(struct kinfo_proc2));
+       mib[5] = (int)(size / sizeof(struct kinfo_proc));
 
        if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
-               (size != sizeof (struct kinfo_proc2))) {
+               (size != sizeof (struct kinfo_proc))) {
                if (errno == ENOMEM) {
                        free(pi);
                        goto retry;
@@ -2256,6 +2258,42 @@ retry:
        return ret;
 }
 
+/*
+ * wapi_process_get_path:
+ *
+ *   Return the full path of the executable of the process PID, or NULL if it cannot be determined.
+ * Returns malloc-ed memory.
+ */
+gchar*
+wapi_process_get_path (pid_t pid)
+{
+#if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX)
+       gchar buf [PROC_PIDPATHINFO_MAXSIZE];
+       int res;
+
+       res = proc_pidpath (pid, buf, sizeof (buf));
+       if (res <= 0)
+               return NULL;
+       if (buf [0] == '\0')
+               return NULL;
+       return g_strdup (buf);
+#else
+       return get_process_name_from_proc (pid);
+#endif
+}
+
+/*
+ * wapi_process_set_cli_launcher:
+ *
+ *   Set the full path of the runtime executable used to launch managed exe's.
+ */
+void
+wapi_process_set_cli_launcher (char *path)
+{
+       g_free (cli_launcher);
+       cli_launcher = path ? g_strdup (path) : NULL;
+}
+
 static guint32 get_module_name (gpointer process, gpointer module,
                                gunichar2 *basename, guint32 size,
                                gboolean base)
@@ -2828,8 +2866,7 @@ process_close (gpointer handle, gpointer data)
 }
 
 #if HAVE_SIGACTION
-static void
-mono_sigchld_signal_handler (int _dummy, siginfo_t *info, void *context)
+MONO_SIGNAL_HANDLER_FUNC (static, mono_sigchld_signal_handler, (int _dummy, siginfo_t *info, void *context))
 {
        int status;
        int pid;
@@ -2870,6 +2907,7 @@ mono_sigchld_signal_handler (int _dummy, siginfo_t *info, void *context)
        fprintf (stdout, "SIG CHILD handler: done looping.");
 #endif
 }
+
 #endif
 
 static void process_add_sigchld_handler (void)
@@ -2897,7 +2935,7 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
        gboolean spin;
        gpointer current_thread;
 
-       current_thread = _wapi_thread_handle_from_id (pthread_self ());
+       current_thread = wapi_get_current_thread_handle ();
        if (current_thread == NULL) {
                SetLastError (ERROR_INVALID_HANDLE);
                return WAIT_FAILED;
@@ -3021,3 +3059,8 @@ static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertabl
        return WAIT_OBJECT_0;
 }
 
+void
+wapi_processes_cleanup (void)
+{
+       g_free (cli_launcher);
+}