Merge pull request #1081 from rneatherway/bug17537
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Wed, 31 Dec 2014 11:38:41 +0000 (12:38 +0100)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Wed, 31 Dec 2014 11:38:41 +0000 (12:38 +0100)
Allow CLR binaries to be passed to Process.Start

1  2 
mono/io-layer/processes.c
mono/tests/Makefile.am

index 3c0531f3de0fd68b07a18dbf3e4535758982a910,590233e0b695d038655d45ca937a67b5dd407f28..65e32011199c7899ce7a362e270541d1628e28dd
@@@ -86,7 -86,7 +86,7 @@@
   * arm-apple-darwin9.  We'll manually define the symbol on Apple as it does
   * in fact exist on all implementations (so far) 
   */
 -gchar ***_NSGetEnviron(void);
 +char ***_NSGetEnviron(void);
  #define environ (*_NSGetEnviron())
  #else
  extern char **environ;
@@@ -142,25 -142,22 +142,25 @@@ static volatile gint32 mono_processes_c
  static mono_mutex_t mono_processes_mutex;
  static void mono_processes_cleanup (void);
  
 -static mono_once_t process_current_once=MONO_ONCE_INIT;
 -static gpointer current_process=NULL;
 +static gpointer current_process;
  static char *cli_launcher;
  
 -static mono_once_t process_ops_once=MONO_ONCE_INIT;
 -
 -static void process_ops_init (void)
 +static WapiHandle_process *
 +lookup_process_handle (gpointer handle)
  {
 -      _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
 -                                          WAPI_HANDLE_CAP_WAIT |
 -                                          WAPI_HANDLE_CAP_SPECIAL_WAIT);
 -}
 +      WapiHandle_process *process_data;
 +      gboolean ret;
  
 +      ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
 +                                                         (gpointer *)&process_data);
 +      if (!ret)
 +              return NULL;
 +      return process_data;
 +}
  
  /* Check if a pid is valid - i.e. if a process exists with this pid. */
 -static gboolean is_pid_valid (pid_t pid)
 +static gboolean
 +is_pid_valid (pid_t pid)
  {
        gboolean result = FALSE;
  
        if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
                result = TRUE;
  #else
 -      gchar *dir = g_strdup_printf ("/proc/%d", pid);
 +      char *dir = g_strdup_printf ("/proc/%d", pid);
        if (!access (dir, F_OK))
                result = TRUE;
        g_free (dir);
        return result;
  }
  
 -static void process_set_defaults (struct _WapiHandle_process *process_handle)
 +static void
 +process_set_defaults (WapiHandle_process *process_handle)
  {
        /* These seem to be the defaults on w2k */
        process_handle->min_working_set = 204800;
@@@ -237,6 -233,42 +237,6 @@@ utf16_concat (const gunichar2 *first, .
        return ret;
  }
  
 -#ifdef PLATFORM_MACOSX
 -
 -/* 0 = no detection; -1 = not 10.5 or higher;  1 = 10.5 or higher */
 -static int osx_10_5_or_higher;
 -
 -static void
 -detect_osx_10_5_or_higher (void)
 -{
 -      struct utsname u;
 -      char *p;
 -      int v;
 -      
 -      if (uname (&u) != 0){
 -              osx_10_5_or_higher = 1;
 -              return;
 -      }
 -
 -      p = u.release;
 -      v = atoi (p);
 -      
 -      if (v < 9)
 -              osx_10_5_or_higher = -1;
 -      else 
 -              osx_10_5_or_higher = 1;
 -}
 -
 -static gboolean
 -is_macos_10_5_or_higher (void)
 -{
 -      if (osx_10_5_or_higher == 0)
 -              detect_osx_10_5_or_higher ();
 -      
 -      return (osx_10_5_or_higher == 1);
 -}
 -#endif
 -
  static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
  static const gunichar2 *utf16_space = utf16_space_bytes; 
  static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
@@@ -247,7 -279,7 +247,7 @@@ static const gunichar2 *utf16_quote = u
  void
  print_utf16 (gunichar2 *str)
  {
 -      gchar *res;
 +      char *res;
  
        res = g_utf16_to_utf8 (str, -1, NULL, NULL, NULL);
        g_print ("%s\n", res);
  #endif
  
  /* Implemented as just a wrapper around CreateProcess () */
 -gboolean ShellExecuteEx (WapiShellExecuteInfo *sei)
 +gboolean
 +ShellExecuteEx (WapiShellExecuteInfo *sei)
  {
        gboolean ret;
        WapiProcessInformation process_info;
                 * that
                 */
                SetLastError (ERROR_INVALID_PARAMETER);
 -              return (FALSE);
 +              return FALSE;
        }
  
 -      if (sei->lpFile == NULL) {
 +      if (sei->lpFile == NULL)
                /* w2k returns TRUE for this, for some reason. */
 -              return (TRUE);
 -      }
 +              return TRUE;
        
        /* Put both executable and parameters into the second argument
         * to CreateProcess (), so it searches $PATH.  The conversion
         * g_strdup_printf () equivalent for gunichar2 :-(
         */
        args = utf16_concat (utf16_quote, sei->lpFile, utf16_quote, sei->lpParameters == NULL ? NULL : utf16_space, sei->lpParameters, NULL);
 -      if (args == NULL){
 +      if (args == NULL) {
                SetLastError (ERROR_INVALID_DATA);
 -              return (FALSE);
 +              return FALSE;
        }
        ret = CreateProcess (NULL, args, NULL, NULL, TRUE,
                             CREATE_UNICODE_ENVIRONMENT, NULL,
                                handler = g_find_program_in_path ("kfmclient");
                                if (handler == NULL){
                                        handler_utf16 = (gunichar2 *) -1;
 -                                      return (FALSE);
 +                                      return FALSE;
                                } else {
                                        /* kfmclient needs exec argument */
                                        char *old = handler;
                                     sei->lpFile, utf16_quote,
                                     sei->lpParameters == NULL ? NULL : utf16_space,
                                     sei->lpParameters, NULL);
 -              if (args == NULL){
 +              if (args == NULL) {
                        SetLastError (ERROR_INVALID_DATA);
                        return FALSE;
                }
                                     CREATE_UNICODE_ENVIRONMENT, NULL,
                                     sei->lpDirectory, NULL, &process_info);
                g_free (args);
 -              if (!ret){
 +              if (!ret) {
                        if (GetLastError () != ERROR_OUTOFMEMORY)
                                SetLastError (ERROR_INVALID_DATA);
                        return FALSE;
                process_info.hProcess = NULL;
        }
        
 -      if (sei->fMask & SEE_MASK_NOCLOSEPROCESS) {
 +      if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
                sei->hProcess = process_info.hProcess;
 -      } else {
 +      else
                CloseHandle (process_info.hProcess);
 -      }
        
 -      return (ret);
 +      return ret;
  }
  
  static gboolean
 -is_managed_binary (const gchar *filename)
 +is_managed_binary (const char *filename)
  {
        int original_errno = errno;
  #if defined(HAVE_LARGE_FILE_SUPPORT) && defined(O_LARGEFILE)
@@@ -472,23 -505,35 +472,36 @@@ leave
        return managed;
  }
  
 -gboolean CreateProcessWithLogonW (const gunichar2 *username,
 -                                const gunichar2 *domain,
 -                                const gunichar2 *password,
 -                                const guint32 logonFlags,
 -                                const gunichar2 *appname,
 -                                const gunichar2 *cmdline,
 -                                guint32 create_flags,
 -                                gpointer env,
 -                                const gunichar2 *cwd,
 -                                WapiStartupInfo *startup,
 -                                WapiProcessInformation *process_info)
 +gboolean
 +CreateProcessWithLogonW (const gunichar2 *username,
 +                                               const gunichar2 *domain,
 +                                               const gunichar2 *password,
 +                                               const guint32 logonFlags,
 +                                               const gunichar2 *appname,
 +                                               const gunichar2 *cmdline,
 +                                               guint32 create_flags,
 +                                               gpointer env,
 +                                               const gunichar2 *cwd,
 +                                               WapiStartupInfo *startup,
 +                                               WapiProcessInformation *process_info)
  {
        /* FIXME: use user information */
        return CreateProcess (appname, cmdline, NULL, NULL, FALSE, create_flags, env, cwd, startup, process_info);
  }
  
+ static gboolean
+ is_readable (const char *prog)
+ {
+       struct stat buf;
+       if (access (prog, R_OK) != 0)
+               return FALSE;
+       if (stat (prog, &buf))
+               return FALSE;
+       if (S_ISREG (buf.st_mode))
+               return TRUE;
+       return FALSE;
+ }
  static gboolean
  is_executable (const char *prog)
  {
  }
  
  static void
 -switchDirectorySeparators(gchar *path)
 +switch_dir_separators (char *path)
  {
        size_t i, pathLength = strlen(path);
        
        /* Turn all the slashes round the right way, except for \' */
        /* There are probably other characters that need to be excluded as well. */
 -      for (i = 0; i < pathLength; i++)
 -      {
 -              if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' ) {
 +      for (i = 0; i < pathLength; i++) {
 +              if (path[i] == '\\' && i < pathLength - 1 && path[i+1] != '\'' )
                        path[i] = '/';
 -              }
        }
  }
  
@@@ -523,12 -570,11 +536,12 @@@ gboolean CreateProcess (const gunichar
                        WapiStartupInfo *startup,
                        WapiProcessInformation *process_info)
  {
 -      gchar *cmd=NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL, *dir = NULL, **env_strings = NULL, **argv = NULL;
 +      char *cmd = NULL, *prog = NULL, *full_prog = NULL, *args = NULL, *args_after_prog = NULL;
 +      char *dir = NULL, **env_strings = NULL, **argv = NULL;
        guint32 i, env_count = 0;
        gboolean ret = FALSE;
        gpointer handle;
 -      struct _WapiHandle_process process_handle = {0}, *process_handle_data;
 +      WapiHandle_process process_handle = {0}, *process_handle_data;
        GError *gerr = NULL;
        int in_fd, out_fd, err_fd;
        pid_t pid;
        int dummy;
        struct MonoProcess *mono_process;
        gboolean fork_failed = FALSE;
 -      
 -      mono_once (&process_ops_once, process_ops_init);
 +
        mono_once (&process_sig_chld_once, process_add_sigchld_handler);
 -      
 +
        /* appname and cmdline specify the executable and its args:
         *
         * If appname is not NULL, it is the name of the executable.
                        goto free_strings;
                }
  
 -              switchDirectorySeparators(cmd);
 +              switch_dir_separators(cmd);
        }
        
        if (cmdline != NULL) {
                }
  
                /* Turn all the slashes round the right way */
 -              switchDirectorySeparators(dir);
 +              switch_dir_separators(dir);
        }
        
  
        /* We can't put off locating the executable any longer :-( */
        if (cmd != NULL) {
 -              gchar *unquoted;
 +              char *unquoted;
                if (g_ascii_isalpha (cmd[0]) && (cmd[1] == ':')) {
                        /* Strip off the drive letter.  I can't
                         * believe that CP/M holdover is still
                        prog = g_strdup (unquoted);
  
                        /* Executable existing ? */
-                       if (!is_executable (prog)) {
+                       if (!is_readable (prog)) {
                                DEBUG ("%s: Couldn't find executable %s",
                                           __func__, prog);
                                g_free (unquoted);
                        prog = g_strdup_printf ("%s/%s", curdir, unquoted);
                        g_free (curdir);
  
-                       /* And make sure it's executable */
-                       if (!is_executable (prog)) {
+                       /* And make sure it's readable */
+                       if (!is_readable (prog)) {
                                DEBUG ("%s: Couldn't find executable %s",
                                           __func__, prog);
                                g_free (unquoted);
  
                args_after_prog = args;
        } else {
 -              gchar *token = NULL;
 +              char *token = NULL;
                char quote;
                
                /* Dig out the first token from args, taking quotation
                /* Turn all the slashes round the right way. Only for
                 * the prg. name
                 */
 -              switchDirectorySeparators(token);
 +              switch_dir_separators(token);
  
                if (g_ascii_isalpha (token[0]) && (token[1] == ':')) {
                        /* Strip off the drive letter.  I can't
                        prog = g_strdup (token);
                        
                        /* Executable existing ? */
-                       if (!is_executable (prog)) {
+                       if (!is_readable (prog)) {
                                DEBUG ("%s: Couldn't find executable %s",
                                           __func__, token);
                                g_free (token);
                                SetLastError (ERROR_FILE_NOT_FOUND);
                                goto free_strings;
                        }
 -
                } else {
                        char *curdir = g_get_current_dir ();
  
  
                        /* I assume X_OK is the criterion to use,
                         * rather than F_OK
+                        *
+                        * X_OK is too strict *if* the target is a CLR binary
                         */
-                       if (!is_executable (prog)) {
+                       if (!is_readable (prog)) {
                                g_free (prog);
                                prog = g_find_program_in_path (token);
                                if (prog == NULL) {
                                goto free_strings;
                        }
                }
+       } else {
+               if (!is_executable (prog)) {
+                       DEBUG ("%s: Executable permisson not set on %s", __func__, prog);
+                       g_free (prog);
+                       SetLastError (ERROR_ACCESS_DENIED);
+                       goto free_strings;
+               }
        }
  
        if (args_after_prog != NULL && *args_after_prog) {
 -              gchar *qprog;
 +              char *qprog;
  
                qprog = g_shell_quote (prog);
                full_prog = g_strconcat (qprog, " ", args_after_prog, NULL);
                err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
        }
        
 -      g_strlcpy (process_handle.proc_name, prog,
 -                 _WAPI_PROC_NAME_MAX_LEN - 1);
 +      process_handle.proc_name = g_strdup (prog);
  
        process_set_defaults (&process_handle);
        
         * environment variables in the new process.  Otherwise the
         * new process inherits the same environment.
         */
 -      if (new_environ != NULL) {
 +      if (new_environ) {
                gunichar2 *new_environp;
  
                /* Count the number of strings */
                /* +2: one for the process handle value, and the last
                 * one is NULL
                 */
 -              env_strings = g_new0 (gchar *, env_count + 2);
 +              env_strings = g_new0 (char *, env_count + 2);
                
                /* Copy each environ string into 'strings' turning it
                 * into utf8 (or the requested encoding) at the same
                        }
                }
        } else {
 -              for (i = 0; environ[i] != NULL; i++) {
 +              for (i = 0; environ[i] != NULL; i++)
                        env_count++;
 -              }
  
                /* +2: one for the process handle value, and the last
                 * one is NULL
                 */
 -              env_strings = g_new0 (gchar *, env_count + 2);
 +              env_strings = g_new0 (char *, env_count + 2);
                
                /* Copy each environ string into 'strings' turning it
                 * into utf8 (or the requested encoding) at the same
                        env_count++;
                }
        }
 -      /* pass process handle info to the child, so it doesn't have
 -       * to do an expensive search over the whole list
 -       */
 -      if (env_strings != NULL) {
 -              struct _WapiHandleUnshared *handle_data;
 -              struct _WapiHandle_shared_ref *ref;
 -              
 -              handle_data = &_WAPI_PRIVATE_HANDLES(GPOINTER_TO_UINT(handle));
 -              ref = &handle_data->u.shared;
 -              
 -              env_strings[env_count] = g_strdup_printf ("_WAPI_PROCESS_HANDLE_OFFSET=%d", ref->offset);
 -      }
  
        /* Create a pipe to make sure the child doesn't exit before 
         * we can add the process to the linked list of mono_processes */
                }
                
                /* Close all file descriptors */
 -              for (i = getdtablesize () - 1; i > 2; i--) {
 +              for (i = wapi_getdtablesize () - 1; i > 2; i--)
                        close (i);
 -              }
  
  #ifdef DEBUG_ENABLED
                DEBUG ("%s: exec()ing [%s] in dir [%s]", __func__, cmd,
 -                         dir==NULL?".":dir);
 -              for (i = 0; argv[i] != NULL; i++) {
 +                         dir == NULL?".":dir);
 +              for (i = 0; argv[i] != NULL; i++)
                        g_message ("arg %d: [%s]", i, argv[i]);
 -              }
                
 -              for (i = 0; env_strings[i] != NULL; i++) {
 +              for (i = 0; env_strings[i] != NULL; i++)
                        g_message ("env %d: [%s]", i, env_strings[i]);
 -              }
  #endif
  
                /* set cwd */
        }
        /* parent */
        
 -      ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
 -                                 (gpointer *)&process_handle_data);
 -      if (ret == FALSE) {
 +      process_handle_data = lookup_process_handle (handle);
 +      if (!process_handle_data) {
                g_warning ("%s: error looking up process handle %p", __func__,
                           handle);
                _wapi_handle_unref (handle);
                _wapi_handle_ref (handle);
                mono_process->handle = handle;
  
 -              process_handle_data->self = _wapi_getpid ();
                process_handle_data->mono_process = mono_process;
  
                mono_mutex_lock (&mono_processes_mutex);
@@@ -1037,20 -1113,27 +1059,20 @@@ cleanup
        }
  
  free_strings:
 -      if (cmd != NULL) {
 +      if (cmd)
                g_free (cmd);
 -      }
 -      if (full_prog != NULL) {
 +      if (full_prog)
                g_free (full_prog);
 -      }
 -      if (prog != NULL) {
 +      if (prog)
                g_free (prog);
 -      }
 -      if (args != NULL) {
 +      if (args)
                g_free (args);
 -      }
 -      if (dir != NULL) {
 +      if (dir)
                g_free (dir);
 -      }
 -      if(env_strings != NULL) {
 +      if (env_strings)
                g_strfreev (env_strings);
 -      }
 -      if (argv != NULL) {
 +      if (argv)
                g_strfreev (argv);
 -      }
        
        DEBUG ("%s: returning handle %p for pid %d", __func__, handle,
                   pid);
        /* Check if something needs to be cleaned up. */
        mono_processes_cleanup ();
        
 -      return(ret);
 +      return ret;
  }
                
 -static void process_set_name (struct _WapiHandle_process *process_handle)
 +static void
 +process_set_name (WapiHandle_process *process_handle)
  {
 -      gchar *progname, *utf8_progname, *slash;
 +      char *progname, *utf8_progname, *slash;
        
 -      progname=g_get_prgname ();
 -      utf8_progname=mono_utf8_from_external (progname);
 +      progname = g_get_prgname ();
 +      utf8_progname = mono_utf8_from_external (progname);
  
        DEBUG ("%s: using [%s] as prog name", __func__, progname);
  
 -      if(utf8_progname!=NULL) {
 -              slash=strrchr (utf8_progname, '/');
 -              if(slash!=NULL) {
 -                      g_strlcpy (process_handle->proc_name, slash+1,
 -                                 _WAPI_PROC_NAME_MAX_LEN - 1);
 -              } else {
 -                      g_strlcpy (process_handle->proc_name, utf8_progname,
 -                                 _WAPI_PROC_NAME_MAX_LEN - 1);
 -              }
 -
 +      if (utf8_progname) {
 +              slash = strrchr (utf8_progname, '/');
 +              if (slash)
 +                      process_handle->proc_name = g_strdup (slash+1);
 +              else
 +                      process_handle->proc_name = g_strdup (utf8_progname);
                g_free (utf8_progname);
        }
  }
  
 -extern void _wapi_time_t_to_filetime (time_t timeval, WapiFileTime *filetime);
 -
 -#if !GLIB_CHECK_VERSION (2,4,0)
 -#define g_setenv(a,b,c) setenv(a,b,c)
 -#define g_unsetenv(a) unsetenv(a)
 -#endif
 -
 -static void process_set_current (void)
 +void
 +wapi_processes_init (void)
  {
        pid_t pid = _wapi_getpid ();
 -      const char *handle_env;
 -      struct _WapiHandle_process process_handle = {0};
 -      
 -      mono_once (&process_ops_once, process_ops_init);
 -      
 -      handle_env = g_getenv ("_WAPI_PROCESS_HANDLE_OFFSET");
 -      g_unsetenv ("_WAPI_PROCESS_HANDLE_OFFSET");
 -      
 -      if (handle_env != NULL) {
 -              struct _WapiHandle_process *process_handlep;
 -              gchar *procname = NULL;
 -              gboolean ok;
 -              
 -              current_process = _wapi_handle_new_from_offset (WAPI_HANDLE_PROCESS, atoi (handle_env), TRUE);
 -              
 -              DEBUG ("%s: Found my process handle: %p (offset %d 0x%x)",
 -                         __func__, current_process, atoi (handle_env),
 -                         atoi (handle_env));
 -
 -              ok = _wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *)&process_handlep);
 -              if (ok) {
 -                      /* This test will probably break on linuxthreads, but
 -                       * that should be ancient history on all distros we
 -                       * care about by now
 -                       */
 -                      if (process_handlep->id == pid) {
 -                              procname = process_handlep->proc_name;
 -                              if (!strcmp (procname, "mono")) {
 -                                      /* Set a better process name */
 -                                      DEBUG ("%s: Setting better process name", __func__);
 -                                      
 -                                      process_set_name (process_handlep);
 -                              } else {
 -                                      DEBUG ("%s: Leaving process name: %s", __func__, procname);
 -                              }
 -
 -                              return;
 -                      }
 -
 -                      /* Wrong pid, so drop this handle and fall through to
 -                       * create a new one
 -                       */
 -                      _wapi_handle_unref (current_process);
 -              }
 -      }
 -
 -      /* We get here if the handle wasn't specified in the
 -       * environment, or if the process ID was wrong, or if the
 -       * handle lookup failed (eg if the parent process forked and
 -       * quit immediately, and deleted the shared data before the
 -       * child got a chance to attach it.)
 -       */
 -
 -      DEBUG ("%s: Need to create my own process handle", __func__);
 +      WapiHandle_process process_handle = {0};
  
 +      _wapi_handle_register_capabilities (WAPI_HANDLE_PROCESS,
 +                                          WAPI_HANDLE_CAP_WAIT |
 +                                          WAPI_HANDLE_CAP_SPECIAL_WAIT);
 +      
        process_handle.id = pid;
  
        process_set_defaults (&process_handle);
  
        current_process = _wapi_handle_new (WAPI_HANDLE_PROCESS,
                                            &process_handle);
 -      if (current_process == _WAPI_HANDLE_INVALID) {
 -              g_warning ("%s: error creating process handle", __func__);
 -              return;
 -      }
 +      g_assert (current_process);
  }
  
 -gpointer _wapi_process_duplicate ()
 +gpointer
 +_wapi_process_duplicate (void)
  {
 -      mono_once (&process_current_once, process_set_current);
 -      
        _wapi_handle_ref (current_process);
        
 -      return(current_process);
 +      return current_process;
  }
  
  /* Returns a pseudo handle that doesn't need to be closed afterwards */
 -gpointer GetCurrentProcess (void)
 +gpointer
 +GetCurrentProcess (void)
  {
 -      mono_once (&process_current_once, process_set_current);
 -              
 -      return(_WAPI_PROCESS_CURRENT);
 +      return _WAPI_PROCESS_CURRENT;
  }
  
 -guint32 GetProcessId (gpointer handle)
 +guint32
 +GetProcessId (gpointer handle)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
  
 -      if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
                /* This is a pseudo handle */
 -              return(GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 -      }
 +              return WAPI_HANDLE_TO_PID (handle);
        
 -      ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
 -                                (gpointer *)&process_handle);
 -      if (ok == FALSE) {
 +      process_handle = lookup_process_handle (handle);
 +      if (!process_handle) {
                SetLastError (ERROR_INVALID_HANDLE);
 -              return (0);
 +              return 0;
        }
        
 -      return (process_handle->id);
 +      return process_handle->id;
  }
  
 -guint32 GetCurrentProcessId (void)
 +static gboolean
 +process_open_compare (gpointer handle, gpointer user_data)
  {
 -      mono_once (&process_current_once, process_set_current);
 -              
 -      return (GetProcessId (current_process));
 -}
 +      pid_t wanted_pid;
 +      WapiHandle_process *process_handle;
 +      pid_t checking_pid;
  
 -/* Returns the process id as a convenience to the functions that call this */
 -static pid_t signal_process_if_gone (gpointer handle)
 -{
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
        
 -      g_assert ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) != _WAPI_PROCESS_UNHANDLED);
 -      
 -      /* Make sure the process is signalled if it has exited - if
 -       * the parent process didn't wait for it then it won't be
 -       */
 -      ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS,
 -                                (gpointer *)&process_handle);
 -      if (ok == FALSE) {
 -              /* It's possible that the handle has vanished during
 -               * the _wapi_search_handle before it gets here, so
 -               * don't spam the console with warnings.
 -               */
 -/*            g_warning ("%s: error looking up process handle %p",
 -  __func__, handle);*/
 -              
 -              return (0);
 -      }
 +      process_handle = lookup_process_handle (handle);
 +      g_assert (process_handle);
        
        DEBUG ("%s: looking at process %d", __func__, process_handle->id);
  
 -      if (kill (process_handle->id, 0) == -1 &&
 -          (errno == ESRCH ||
 -           errno == EPERM)) {
 -              /* The process is dead, (EPERM tells us a new process
 -               * has that ID, but as it's owned by someone else it
 -               * can't be the one listed in our shared memory file)
 -               */
 -              _wapi_shared_handle_set_signal_state (handle, TRUE);
 -      }
 -
 -      return (process_handle->id);
 -}
 -
 -#ifdef UNUSED_CODE
 -static gboolean process_enum (gpointer handle, gpointer user_data)
 -{
 -      GArray *processes=user_data;
 -      pid_t pid = signal_process_if_gone (handle);
 -      int i;
 -      
 -      if (pid == 0) {
 -              return (FALSE);
 -      }
 -      
 -      /* Ignore processes that have already exited (ie they are signalled) */
 -      if (_wapi_handle_issignalled (handle) == FALSE) {
 -              DEBUG ("%s: process %d added to array", __func__, pid);
 -
 -              /* This ensures that duplicates aren't returned (see
 -               * the comment above _wapi_search_handle () for why
 -               * it's needed
 -               */
 -              for (i = 0; i < processes->len; i++) {
 -                      if (g_array_index (processes, pid_t, i) == pid) {
 -                              /* We've already got this one, return
 -                               * FALSE to keep searching
 -                               */
 -                              return (FALSE);
 -                      }
 -              }
 -              
 -              g_array_append_val (processes, pid);
 -      }
 -      
 -      /* Return false to keep searching */
 -      return(FALSE);
 -}
 -#endif /* UNUSED_CODE */
 -
 -#if defined(PLATFORM_MACOSX) || defined(__OpenBSD__)
 -
 -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
 -{
 -      guint32 count, fit, i, j;
 -      gint32 err;
 -      gboolean done;
 -      size_t proclength, size;
 -#if defined(__OpenBSD__)
 -      struct kinfo_proc *result;
 -      int name[6];
 -      name[0] = CTL_KERN;
 -      name[1] = KERN_PROC;
 -      name[2] = KERN_PROC_ALL;
 -      name[3] = 0;
 -      name[4] = sizeof(struct kinfo_proc);
 -      name[5] = 0;
 -#else
 -      struct kinfo_proc *result;
 -      static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
 -#endif
 -
 -      mono_once (&process_current_once, process_set_current);
 -
 -      result = NULL;
 -      done = FALSE;
 -
 -      do {
 -              proclength = 0;
 -#if defined(__OpenBSD__)
 -              size = (sizeof(name) / sizeof(*name));
 -#else
 -              size = (sizeof(name) / sizeof(*name)) - 1;
 -#endif
 -              err = sysctl ((int *)name, size, NULL, &proclength, NULL, 0);
 -
 -              if (err == 0) {
 -                      result = malloc (proclength);
 -
 -                      if (result == NULL)
 -                              return FALSE;
 +      checking_pid = process_handle->id;
  
 -#if defined(__OpenBSD__)
 -                      name[5] = (int)(proclength / sizeof(struct kinfo_proc));
 -#endif
 -
 -                      err = sysctl ((int *) name, size, result, &proclength, NULL, 0);
 -
 -                      if (err == 0) 
 -                              done = TRUE;
 -                      else {
 -                              free (result);
 -                              result = NULL;
 -                      }
 -              }
 -      } while (err == 0 && !done);
 -      
 -      if (err != 0) {
 -              if (result != NULL) {
 -                      free (result);
 -                      result = NULL;
 -              }
 -              return(FALSE);
 -      }       
 -
 -      count = proclength / sizeof(struct kinfo_proc);
 -
 -      fit = len / sizeof(guint32);
 -      for (i = 0, j = 0; j< fit && i < count; i++) {
 -#if defined(__OpenBSD__)
 -              pids [j++] = result [i].p_pid;
 -#else
 -              if (result[i].kp_proc.p_pid > 0) /* Pid 0 not supported */
 -                      pids [j++] = result [i].kp_proc.p_pid;
 -#endif
 -      }
 -      free (result);
 -      result = NULL;
 -      *needed = j * sizeof(guint32);
 -      
 -      return(TRUE);
 -}
 -#elif defined(__HAIKU__)
 -
 -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
 -{
 -      guint32 fit, i = 0;
 -      int32 cookie = 0;
 -      team_info teamInfo;
 -
 -      mono_once (&process_current_once, process_set_current);
 -
 -      fit = len / sizeof (guint32);
 -      while (get_next_team_info (&cookie, &teamInfo) == B_OK && i < fit) {
 -              pids [i++] = teamInfo.team;
 -      }
 -      *needed = i * sizeof (guint32);
 -
 -      return TRUE;
 -}
 -#else
 -gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed)
 -{
 -      guint32 fit, i;
 -      DIR *dir;
 -      struct dirent *entry;
 -      
 -      mono_once (&process_current_once, process_set_current);
 -
 -      dir = opendir ("/proc");
 -      if (dir == NULL) {
 -              return(FALSE);
 -      }
 -
 -      i = 0;
 -      fit = len / sizeof (guint32);
 -      while(i < fit && (entry = readdir (dir)) != NULL) {
 -              pid_t pid;
 -              char *endptr;
 -
 -              if (!isdigit (entry->d_name[0]))
 -                      continue;
 -
 -              pid = (pid_t) strtol (entry->d_name, &endptr, 10);
 -              if (*endptr == '\0')
 -                      pids [i++] = (guint32) pid;
 -      }
 -      closedir (dir);
 -      *needed = i * sizeof(guint32);
 -      
 -      return(TRUE);
 -}
 -#endif
 -
 -static gboolean process_open_compare (gpointer handle, gpointer user_data)
 -{
 -      pid_t wanted_pid;
 -      pid_t checking_pid = signal_process_if_gone (handle);
 -
 -      if (checking_pid == 0) {
 -              return(FALSE);
 -      }
 +      if (checking_pid == 0)
 +              return FALSE;
        
        wanted_pid = GPOINTER_TO_UINT (user_data);
  
         * unsignalled
         */
        if (checking_pid == wanted_pid &&
 -          _wapi_handle_issignalled (handle) == FALSE) {
 +          !_wapi_handle_issignalled (handle)) {
                /* If the handle is blown away in the window between
                 * returning TRUE here and _wapi_search_handle pinging
                 * the timestamp, the search will continue
                 */
 -              return(TRUE);
 +              return TRUE;
        } else {
 -              return(FALSE);
 +              return FALSE;
        }
  }
  
 -gboolean CloseProcess(gpointer handle)
 +gboolean
 +CloseProcess (gpointer handle)
  {
 -      if ((GPOINTER_TO_UINT (handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 -              /* This is a pseudo handle */
 -              return(TRUE);
 -      }
 -
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
 +              return TRUE;
        return CloseHandle (handle);
  }
  
  /*
   * The caller owns the returned handle and must call CloseProcess () on it to clean it up.
   */
 -gpointer OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
 +gpointer
 +OpenProcess (guint32 req_access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 pid)
  {
        /* Find the process handle that corresponds to pid */
        gpointer handle = NULL;
        
 -      mono_once (&process_current_once, process_set_current);
 -
        DEBUG ("%s: looking for process %d", __func__, pid);
  
        handle = _wapi_search_handle (WAPI_HANDLE_PROCESS,
                        /* Return a pseudo handle for processes we
                         * don't have handles for
                         */
 -                      return GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + pid);
 +                      return WAPI_PID_TO_HANDLE (pid);
                } else {
                        DEBUG ("%s: Can't find pid %d", __func__, pid);
  
                        SetLastError (ERROR_PROC_NOT_FOUND);
        
 -                      return(NULL);
 +                      return NULL;
                }
        }
  
        /* _wapi_search_handle () already added a ref */
 -      return(handle);
 +      return handle;
  }
  
 -gboolean GetExitCodeProcess (gpointer process, guint32 *code)
 +gboolean
 +GetExitCodeProcess (gpointer process, guint32 *code)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        guint32 pid = -1;
        
 -      mono_once (&process_current_once, process_set_current);
 -
 -      if(code==NULL) {
 -              return(FALSE);
 -      }
 +      if (!code)
 +              return FALSE;
        
 -      pid = GPOINTER_TO_UINT (process) - _WAPI_PROCESS_UNHANDLED;
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
 +              pid = WAPI_HANDLE_TO_PID (process);
                /* This is a pseudo handle, so we don't know what the
                 * exit code was, but we can check whether it's alive or not
                 */
                }
        }
  
 -      ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                              (gpointer *)&process_handle);
 -      if(ok==FALSE) {
 +      process_handle = lookup_process_handle (process);
 +      if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
 -              return(FALSE);
 +              return FALSE;
        }
        
        /* A process handle is only signalled if the process has exited
         */
        process_wait (process, 0, TRUE);
        
 -      if (_wapi_handle_issignalled (process) == TRUE) {
 +      if (_wapi_handle_issignalled (process))
                *code = process_handle->exitstatus;
 -      } else {
 +      else
                *code = STILL_ACTIVE;
 -      }
        
 -      return(TRUE);
 +      return TRUE;
  }
  
 -gboolean GetProcessTimes (gpointer process, WapiFileTime *create_time,
 -                        WapiFileTime *exit_time, WapiFileTime *kernel_time,
 -                        WapiFileTime *user_time)
 +gboolean
 +GetProcessTimes (gpointer process, WapiFileTime *create_time,
 +                               WapiFileTime *exit_time, WapiFileTime *kernel_time,
 +                               WapiFileTime *user_time)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        gboolean ku_times_set = FALSE;
        
 -      mono_once (&process_current_once, process_set_current);
 -
 -      if(create_time==NULL || exit_time==NULL || kernel_time==NULL ||
 -         user_time==NULL) {
 +      if (create_time == NULL || exit_time == NULL || kernel_time == NULL ||
 +              user_time == NULL)
                /* Not sure if w32 allows NULLs here or not */
 -              return(FALSE);
 -      }
 +              return FALSE;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
                /* This is a pseudo handle, so just fail for now
                 */
 -              return(FALSE);
 -      }
 +              return FALSE;
        
 -      ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                              (gpointer *)&process_handle);
 -      if(ok==FALSE) {
 +      process_handle = lookup_process_handle (process);
 +      if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
 -              return(FALSE);
 +              return FALSE;
        }
        
 -      *create_time=process_handle->create_time;
 +      *create_time = process_handle->create_time;
  
        /* A process handle is only signalled if the process has
         * exited.  Otherwise exit_time isn't set
         */
 -      if(_wapi_handle_issignalled (process)==TRUE) {
 -              *exit_time=process_handle->exit_time;
 -      }
 +      if (_wapi_handle_issignalled (process))
 +              *exit_time = process_handle->exit_time;
  
  #ifdef HAVE_GETRUSAGE
        if (process_handle->id == getpid ()) {
                memset (user_time, 0, sizeof (WapiFileTime));
        }
  
 -      return(TRUE);
 +      return TRUE;
  }
  
  typedef struct
  {
        gpointer address_start;
        gpointer address_end;
 -      gchar *perms;
 +      char *perms;
        gpointer address_offset;
        dev_t device;
        ino_t inode;
 -      gchar *filename;
 +      char *filename;
  } WapiProcModule;
  
  static void free_procmodule (WapiProcModule *mod)
@@@ -1496,9 -1865,9 +1518,9 @@@ static GSList *load_modules (FILE *fp
  {
        GSList *ret = NULL;
        WapiProcModule *mod;
 -      gchar buf[MAXPATHLEN + 1], *p, *endp;
 -      gchar *start_start, *end_start, *prot_start, *offset_start;
 -      gchar *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
 +      char buf[MAXPATHLEN + 1], *p, *endp;
 +      char *start_start, *end_start, *prot_start, *offset_start;
 +      char *maj_dev_start, *min_dev_start, *inode_start, prot_buf[5];
        gpointer address_start, address_end, address_offset;
        guint32 maj_dev, min_dev;
        ino_t inode;
  }
  #endif
  
 -static gboolean match_procname_to_modulename (gchar *procname, gchar *modulename)
 +static gboolean match_procname_to_modulename (char *procname, char *modulename)
  {
        char* lastsep = NULL;
        char* lastsep2 = NULL;
@@@ -1659,13 -2028,13 +1681,13 @@@ static FILE 
  open_process_map (int pid, const char *mode)
  {
        FILE *fp = NULL;
 -      const gchar *proc_path[] = {
 +      const char *proc_path[] = {
                "/proc/%d/maps",        /* GNU/Linux */
                "/proc/%d/map",         /* FreeBSD */
                NULL
        };
        int i;
 -      gchar *filename;
 +      char *filename;
  
        for (i = 0; fp == NULL && proc_path [i]; i++) {
                filename = g_strdup_printf (proc_path[i], pid);
  gboolean EnumProcessModules (gpointer process, gpointer *modules,
                             guint32 size, guint32 *needed)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
  #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
        FILE *fp;
  #endif
        guint32 count, avail = size / sizeof(gpointer);
        int i;
        pid_t pid;
 -      gchar *proc_name = NULL;
 +      char *proc_name = NULL;
        
        /* Store modules in an array of pointers (main module as
         * modules[0]), using the load address for each module as a
         * implement /dev/kmem reading or whatever other horrid
         * technique is needed.
         */
 -      if (size < sizeof(gpointer)) {
 -              return(FALSE);
 -      }
 +      if (size < sizeof(gpointer))
 +              return FALSE;
  
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 -              /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
 +              pid = WAPI_HANDLE_TO_PID (process);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *)&process_handle);
 -              if (ok == FALSE) {
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__, process);
                
 -                      return(FALSE);
 +                      return FALSE;
                }
                pid = process_handle->id;
                proc_name = process_handle->proc_name;
        }
        
  #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
 -      {
 -              mods = load_modules ();
 +      mods = load_modules ();
 +      if (!proc_name) {
 +              modules[0] = NULL;
 +              *needed = sizeof(gpointer);
 +              return TRUE;
 +      }
  #else
 -      if ((fp = open_process_map (pid, "r")) == NULL) {
 +      fp = open_process_map (pid, "r");
 +      if (!fp) {
                /* No /proc/<pid>/maps so just return the main module
                 * shortcut for now
                 */
                modules[0] = NULL;
                *needed = sizeof(gpointer);
 -      } else {
 -              mods = load_modules (fp);
 -              fclose (fp);
 +              return TRUE;
 +      }
 +      mods = load_modules (fp);
 +      fclose (fp);
  #endif
 -              count = g_slist_length (mods);
 +      count = g_slist_length (mods);
                
 -              /* count + 1 to leave slot 0 for the main module */
 -              *needed = sizeof(gpointer) * (count + 1);
 -
 -              /* Use the NULL shortcut, as the first line in
 -               * /proc/<pid>/maps isn't the executable, and we need
 -               * that first in the returned list. Check the module name 
 -               * to see if it ends with the proc name and substitute 
 -               * the first entry with it.  FIXME if this turns out to 
 -               * be a problem.
 -               */
 -              modules[0] = NULL;
 -              for (i = 0; i < (avail - 1) && i < count; i++) {
 -                      module = (WapiProcModule *)g_slist_nth_data (mods, i);
 -                      if (modules[0] != NULL)
 -                              modules[i] = module->address_start;
 -                      else if (match_procname_to_modulename (proc_name, module->filename))
 -                              modules[0] = module->address_start;
 -                      else
 -                              modules[i + 1] = module->address_start;
 -              }
 +      /* count + 1 to leave slot 0 for the main module */
 +      *needed = sizeof(gpointer) * (count + 1);
 +
 +      /*
 +       * Use the NULL shortcut, as the first line in
 +       * /proc/<pid>/maps isn't the executable, and we need
 +       * that first in the returned list. Check the module name 
 +       * to see if it ends with the proc name and substitute 
 +       * the first entry with it.  FIXME if this turns out to 
 +       * be a problem.
 +       */
 +      modules[0] = NULL;
 +      for (i = 0; i < (avail - 1) && i < count; i++) {
 +              module = (WapiProcModule *)g_slist_nth_data (mods, i);
 +              if (modules[0] != NULL)
 +                      modules[i] = module->address_start;
 +              else if (match_procname_to_modulename (proc_name, module->filename))
 +                      modules[0] = module->address_start;
 +              else
 +                      modules[i + 1] = module->address_start;
 +      }
                
 -              for (i = 0; i < count; i++) {
 -                      free_procmodule (g_slist_nth_data (mods, i));
 -              }
 -              g_slist_free (mods);
 +      for (i = 0; i < count; i++) {
 +              free_procmodule (g_slist_nth_data (mods, i));
        }
 +      g_slist_free (mods);
  
 -      return(TRUE);
 +      return TRUE;
  }
  
 -static gchar *get_process_name_from_proc (pid_t pid)
 +static char *
 +get_process_name_from_proc (pid_t pid)
  {
  #if defined(__OpenBSD__)
        int mib [6];
  #endif
  #else
        FILE *fp;
 -      gchar *filename = NULL;
 +      char *filename = NULL;
  #endif
 -      gchar buf[256];
 -      gchar *ret = NULL;
 +      char buf[256];
 +      char *ret = NULL;
  
  #if defined(PLATFORM_SOLARIS)
        filename = g_strdup_printf ("/proc/%d/psinfo", pid);
@@@ -1895,7 -2261,7 +1917,7 @@@ retry
        filename = g_strdup_printf ("/proc/%d/stat", pid);
        if ((fp = fopen (filename, "r")) != NULL) {
                if (fgets (buf, 256, fp) != NULL) {
 -                      gchar *start, *end;
 +                      char *start, *end;
                        
                        start = strchr (buf, '(');
                        if (start != NULL) {
   *   Return the full path of the executable of the process PID, or NULL if it cannot be determined.
   * Returns malloc-ed memory.
   */
 -gchar*
 +char*
  wapi_process_get_path (pid_t pid)
  {
  #if defined(PLATFORM_MACOSX) && !defined(__mono_ppc__) && defined(TARGET_OSX)
 -      gchar buf [PROC_PIDPATHINFO_MAXSIZE];
 +      char buf [PROC_PIDPATHINFO_MAXSIZE];
        int res;
  
        res = proc_pidpath (pid, buf, sizeof (buf));
@@@ -1952,15 -2318,15 +1974,15 @@@ wapi_process_set_cli_launcher (char *pa
        cli_launcher = path ? g_strdup (path) : NULL;
  }
  
 -static guint32 get_module_name (gpointer process, gpointer module,
 -                              gunichar2 *basename, guint32 size,
 -                              gboolean base)
 +static guint32
 +get_module_name (gpointer process, gpointer module,
 +                               gunichar2 *basename, guint32 size,
 +                               gboolean base)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        pid_t pid;
        gunichar2 *procname;
 -      gchar *procname_ext = NULL;
 +      char *procname_ext = NULL;
        glong len;
        gsize bytes;
  #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
        WapiProcModule *found_module;
        guint32 count;
        int i;
 -      gchar *proc_name = NULL;
 +      char *proc_name = NULL;
        
 -      mono_once (&process_current_once, process_set_current);
 -
        DEBUG ("%s: Getting module base name, process handle %p module %p",
                   __func__, process, module);
  
 -      size = size*sizeof(gunichar2); /* adjust for unicode characters */
 +      size = size * sizeof (gunichar2); /* adjust for unicode characters */
  
 -      if (basename == NULL || size == 0) {
 -              return(0);
 -      }
 +      if (basename == NULL || size == 0)
 +              return 0;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +              pid = (pid_t)WAPI_HANDLE_TO_PID (process);
                proc_name = get_process_name_from_proc (pid);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *)&process_handle);
 -              if (ok == FALSE) {
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__,
                                   process);
                        
 -                      return(0);
 +                      return 0;
                }
                pid = process_handle->id;
                proc_name = g_strdup (process_handle->proc_name);
  
        /* Look up the address in /proc/<pid>/maps */
  #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
 -      {
 -              mods = load_modules ();
 +      mods = load_modules ();
  #else
 -      if ((fp = open_process_map (pid, "r")) == NULL) {
 +      fp = open_process_map (pid, "r");
 +      if (fp == NULL) {
                if (errno == EACCES && module == NULL && base == TRUE) {
                        procname_ext = get_process_name_from_proc (pid);
                } else {
                         * for now
                         */
                        g_free (proc_name);
 -                      return(0);
 +                      return 0;
                }
        } else {
                mods = load_modules (fp);
                fclose (fp);
 +      }
  #endif
 -              count = g_slist_length (mods);
 -
 -              /* If module != NULL compare the address.
 -               * If module == NULL we are looking for the main module.
 -               * The best we can do for now check it the module name end with the process name.
 -               */
 -              for (i = 0; i < count; i++) {
 -                      found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
 -                      if (procname_ext == NULL &&
 -                          ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||    
 -                           (module != NULL && found_module->address_start == module))) {
 -                              if (base) {
 -                                      procname_ext = g_path_get_basename (found_module->filename);
 -                              } else {
 -                                      procname_ext = g_strdup (found_module->filename);
 -                              }
 -                      }
 +      count = g_slist_length (mods);
  
 -                      free_procmodule (found_module);
 +      /* If module != NULL compare the address.
 +       * If module == NULL we are looking for the main module.
 +       * The best we can do for now check it the module name end with the process name.
 +       */
 +      for (i = 0; i < count; i++) {
 +              found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
 +              if (procname_ext == NULL &&
 +                      ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
 +                       (module != NULL && found_module->address_start == module))) {
 +                      if (base)
 +                              procname_ext = g_path_get_basename (found_module->filename);
 +                      else
 +                              procname_ext = g_strdup (found_module->filename);
                }
  
 -              if (procname_ext == NULL)
 -              {
 -                      /* If it's *still* null, we might have hit the
 -                       * case where reading /proc/$pid/maps gives an
 -                       * empty file for this user.
 -                       */
 -                      procname_ext = get_process_name_from_proc (pid);
 -              }
 +              free_procmodule (found_module);
 +      }
  
 -              g_slist_free (mods);
 -              g_free (proc_name);
 +      if (procname_ext == NULL) {
 +              /* If it's *still* null, we might have hit the
 +               * case where reading /proc/$pid/maps gives an
 +               * empty file for this user.
 +               */
 +              procname_ext = get_process_name_from_proc (pid);
        }
  
 -      if (procname_ext != NULL) {
 +      g_slist_free (mods);
 +      g_free (proc_name);
 +
 +      if (procname_ext) {
                DEBUG ("%s: Process name is [%s]", __func__,
                           procname_ext);
  
                if (procname == NULL) {
                        /* bugger */
                        g_free (procname_ext);
 -                      return(0);
 +                      return 0;
                }
                
                len = (bytes / 2);
                g_free (procname);
                g_free (procname_ext);
                
 -              return(len);
 +              return len;
        }
        
 -      return(0);
 +      return 0;
  }
  
 -guint32 GetModuleBaseName (gpointer process, gpointer module,
 -                         gunichar2 *basename, guint32 size)
 +guint32
 +GetModuleBaseName (gpointer process, gpointer module,
 +                                 gunichar2 *basename, guint32 size)
  {
 -      return(get_module_name (process, module, basename, size, TRUE));
 +      return get_module_name (process, module, basename, size, TRUE);
  }
  
 -guint32 GetModuleFileNameEx (gpointer process, gpointer module,
 -                           gunichar2 *filename, guint32 size)
 +guint32
 +GetModuleFileNameEx (gpointer process, gpointer module,
 +                                       gunichar2 *filename, guint32 size)
  {
 -      return(get_module_name (process, module, filename, size, FALSE));
 +      return get_module_name (process, module, filename, size, FALSE);
  }
  
 -gboolean GetModuleInformation (gpointer process, gpointer module,
 -                             WapiModuleInfo *modinfo, guint32 size)
 +gboolean
 +GetModuleInformation (gpointer process, gpointer module,
 +                                        WapiModuleInfo *modinfo, guint32 size)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        pid_t pid;
  #if !defined(__OpenBSD__) && !defined(PLATFORM_MACOSX)
        FILE *fp;
        guint32 count;
        int i;
        gboolean ret = FALSE;
 -      gchar *proc_name = NULL;
 -      
 -      mono_once (&process_current_once, process_set_current);
 +      char *proc_name = NULL;
        
        DEBUG ("%s: Getting module info, process handle %p module %p",
                   __func__, process, module);
  
 -      if (modinfo == NULL || size < sizeof(WapiModuleInfo)) {
 -              return(FALSE);
 -      }
 +      if (modinfo == NULL || size < sizeof (WapiModuleInfo))
 +              return FALSE;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 -              /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
 +              pid = (pid_t)WAPI_HANDLE_TO_PID (process);
                proc_name = get_process_name_from_proc (pid);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *)&process_handle);
 -              if (ok == FALSE) {
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
                        DEBUG ("%s: Can't find process %p", __func__,
                                   process);
                        
 -                      return(FALSE);
 +                      return FALSE;
                }
                pid = process_handle->id;
                proc_name = g_strdup (process_handle->proc_name);
        }
  
  #if defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__HAIKU__)
 -      {
 -              mods = load_modules ();
 +      mods = load_modules ();
  #else
        /* Look up the address in /proc/<pid>/maps */
        if ((fp = open_process_map (pid, "r")) == NULL) {
                 * for now
                 */
                g_free (proc_name);
 -              return(FALSE);
 -      } else {
 -              mods = load_modules (fp);
 -              fclose (fp);
 +              return FALSE;
 +      }
 +      mods = load_modules (fp);
 +      fclose (fp);
  #endif
 -              count = g_slist_length (mods);
 +      count = g_slist_length (mods);
  
 -              /* If module != NULL compare the address.
 -               * If module == NULL we are looking for the main module.
 -               * The best we can do for now check it the module name end with the process name.
 -               */
 -              for (i = 0; i < count; i++) {
 +      /* If module != NULL compare the address.
 +       * If module == NULL we are looking for the main module.
 +       * The best we can do for now check it the module name end with the process name.
 +       */
 +      for (i = 0; i < count; i++) {
                        found_module = (WapiProcModule *)g_slist_nth_data (mods, i);
 -                      if ( ret == FALSE &&
 -                           ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
 -                            (module != NULL && found_module->address_start == module))) {
 +                      if (ret == FALSE &&
 +                              ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
 +                               (module != NULL && found_module->address_start == module))) {
                                modinfo->lpBaseOfDll = found_module->address_start;
                                modinfo->SizeOfImage = (gsize)(found_module->address_end) - (gsize)(found_module->address_start);
                                modinfo->EntryPoint = found_module->address_offset;
                        }
  
                        free_procmodule (found_module);
 -              }
 -
 -              g_slist_free (mods);
 -              g_free (proc_name);
        }
  
 -      return(ret);
 +      g_slist_free (mods);
 +      g_free (proc_name);
 +
 +      return ret;
  }
  
 -gboolean GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
 +gboolean
 +GetProcessWorkingSetSize (gpointer process, size_t *min, size_t *max)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        
 -      mono_once (&process_current_once, process_set_current);
 -
 -      if(min==NULL || max==NULL) {
 +      if (min == NULL || max == NULL)
                /* Not sure if w32 allows NULLs here or not */
 -              return(FALSE);
 -      }
 +              return FALSE;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 -              /* This is a pseudo handle, so just fail for now
 -               */
 -              return(FALSE);
 -      }
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
 +              /* This is a pseudo handle, so just fail for now */
 +              return FALSE;
        
 -      ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                              (gpointer *)&process_handle);
 -      if(ok==FALSE) {
 +      process_handle = lookup_process_handle (process);
 +      if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
 -              return(FALSE);
 +              return FALSE;
        }
  
 -      *min=process_handle->min_working_set;
 -      *max=process_handle->max_working_set;
 +      *min = process_handle->min_working_set;
 +      *max = process_handle->max_working_set;
        
 -      return(TRUE);
 +      return TRUE;
  }
  
 -gboolean SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
 +gboolean
 +SetProcessWorkingSetSize (gpointer process, size_t min, size_t max)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
  
 -      mono_once (&process_current_once, process_set_current);
 -      
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process))
                /* This is a pseudo handle, so just fail for now
                 */
 -              return(FALSE);
 -      }
 +              return FALSE;
  
 -      ok=_wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                              (gpointer *)&process_handle);
 -      if(ok==FALSE) {
 +      process_handle = lookup_process_handle (process);
 +      if (!process_handle) {
                DEBUG ("%s: Can't find process %p", __func__, process);
                
 -              return(FALSE);
 +              return FALSE;
        }
  
 -      process_handle->min_working_set=min;
 -      process_handle->max_working_set=max;
 +      process_handle->min_working_set = min;
 +      process_handle->max_working_set = max;
        
 -      return(TRUE);
 +      return TRUE;
  }
  
  
  gboolean
  TerminateProcess (gpointer process, gint32 exitCode)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        int signo;
        int ret;
        pid_t pid;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +              pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *) &process_handle);
 -
 -              if (ok == FALSE) {
 -                      DEBUG ("%s: Can't find process %p", __func__,
 -                                 process);
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
 +                      DEBUG ("%s: Can't find process %p", __func__, process);
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@@ -2270,16 -2661,19 +2292,16 @@@ guint3
  GetPriorityClass (gpointer process)
  {
  #ifdef HAVE_GETPRIORITY
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        int ret;
        pid_t pid;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +              pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *) &process_handle);
 -
 -              if (!ok) {
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@@ -2327,17 -2721,20 +2349,17 @@@ gboolea
  SetPriorityClass (gpointer process, guint32  priority_class)
  {
  #ifdef HAVE_SETPRIORITY
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        int ret;
        int prio;
        pid_t pid;
        
 -      if ((GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED) {
 +      if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
                /* This is a pseudo handle */
 -              pid = (pid_t)(GPOINTER_TO_UINT (process) & _WAPI_PROCESS_UNHANDLED_PID_MASK);
 +              pid = (pid_t)WAPI_HANDLE_TO_PID (process);
        } else {
 -              ok = _wapi_lookup_handle (process, WAPI_HANDLE_PROCESS,
 -                                        (gpointer *) &process_handle);
 -
 -              if (!ok) {
 +              process_handle = lookup_process_handle (process);
 +              if (!process_handle) {
                        SetLastError (ERROR_INVALID_HANDLE);
                        return FALSE;
                }
@@@ -2421,12 -2818,6 +2443,12 @@@ mono_processes_cleanup (void
                mp = mp->next;
        }
  
 +      /*
 +       * Remove processes which exited from the mono_processes list.
 +       * We need to synchronize with the sigchld handler here, which runs
 +       * asynchronously. The handler requires that the mono_processes list
 +       * remain valid.
 +       */
        mp = mono_processes;
        spin = 0;
        while (mp != NULL) {
  
                        /* We've found a candidate */
                        mono_mutex_lock (&mono_processes_mutex);
 +                      /*
 +                       * This code can run parallel with the sigchld handler, but the
 +                       * modifications it makes are safe.
 +                       */
                        if (candidate == NULL) {
                                /* unlink it */
                                if (mp == mono_processes) {
  static void
  process_close (gpointer handle, gpointer data)
  {
 -      struct _WapiHandle_process *process_handle;
 +      WapiHandle_process *process_handle;
  
        DEBUG ("%s", __func__);
  
 -      process_handle = (struct _WapiHandle_process *) data;
 -      if (process_handle->mono_process && process_handle->self == _wapi_getpid ())
 +      process_handle = (WapiHandle_process *) data;
 +      g_free (process_handle->proc_name);
 +      process_handle->proc_name = NULL;
 +      if (process_handle->mono_process)
                InterlockedDecrement (&process_handle->mono_process->handle_count);
        mono_processes_cleanup ();
  }
@@@ -2511,7 -2896,9 +2533,7 @@@ MONO_SIGNAL_HANDLER_FUNC (static, mono_
        int pid;
        struct MonoProcess *p;
  
 -#if DEBUG     
 -      fprintf (stdout, "SIG CHILD handler for pid: %i\n", info->si_pid);
 -#endif
 +      DEBUG ("SIG CHILD handler for pid: %i\n", info->si_pid);
  
        InterlockedIncrement (&mono_processes_read_lock);
  
                if (pid <= 0)
                        break;
  
 -#if DEBUG
 -              fprintf (stdout, "child ended: %i", pid);
 -#endif
 +              DEBUG ("child ended: %i", pid);
                p = mono_processes;
                while (p != NULL) {
                        if (p->pid == pid) {
  
        InterlockedDecrement (&mono_processes_read_lock);
  
 -#if DEBUG
 -      fprintf (stdout, "SIG CHILD handler: done looping.");
 -#endif
 +      DEBUG ("SIG CHILD handler: done looping.");
  }
  
  #endif
  
 -static void process_add_sigchld_handler (void)
 +static void
 +process_add_sigchld_handler (void)
  {
  #if HAVE_SIGACTION
        struct sigaction sa;
  #endif
  }
  
 -static guint32 process_wait (gpointer handle, guint32 timeout, gboolean alertable)
 +static guint32
 +process_wait (gpointer handle, guint32 timeout, gboolean alertable)
  {
 -      struct _WapiHandle_process *process_handle;
 -      gboolean ok;
 +      WapiHandle_process *process_handle;
        pid_t pid, ret;
        int status;
        guint32 start;
        guint32 now;
        struct MonoProcess *mp;
 -      gboolean spin;
 -      gpointer current_thread;
 -
 -      current_thread = wapi_get_current_thread_handle ();
 -      if (current_thread == NULL) {
 -              SetLastError (ERROR_INVALID_HANDLE);
 -              return WAIT_FAILED;
 -      }
  
        /* FIXME: We can now easily wait on processes that aren't our own children,
         * but WaitFor*Object won't call us for pseudo handles. */
  
        DEBUG ("%s (%p, %u)", __func__, handle, timeout);
  
 -      ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, (gpointer *)&process_handle);
 -      if (ok == FALSE) {
 +      process_handle = lookup_process_handle (handle);
 +      if (!process_handle) {
                g_warning ("%s: error looking up process handle %p", __func__, handle);
                return WAIT_FAILED;
        }
        /* 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;
 -      if (mp && process_handle->self != _wapi_getpid ()) {
 -              /* mono_process points to memory in another process' address space: we can't use it */
 -              mp = NULL;
 -      }
 +      g_assert (mp);
  
        start = mono_msec_ticks ();
        now = start;
 -      spin = mp == NULL;
  
        while (1) {
 -              if (mp != NULL) {
 -                      /* We have a semaphore we can wait on */
 -                      if (timeout != INFINITE) {
 -                              DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", 
 -                                      __func__, handle, timeout, (timeout - (now - start)));
 +              if (timeout != INFINITE) {
 +                      DEBUG ("%s (%p, %u): waiting on semaphore for %li ms...", 
 +                                 __func__, handle, timeout, (timeout - (now - start)));
  
 -                              ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable);
 -                      } else {
 -                              DEBUG ("%s (%p, %u): waiting on semaphore forever...", 
 -                                      __func__, handle, timeout);
 -                              ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable);
 -                      }
 +                      ret = MONO_SEM_TIMEDWAIT_ALERTABLE (&mp->exit_sem, (timeout - (now - start)), alertable);
 +              } else {
 +                      DEBUG ("%s (%p, %u): waiting on semaphore forever...", 
 +                                 __func__, handle, timeout);
 +                      ret = MONO_SEM_WAIT_ALERTABLE (&mp->exit_sem, alertable);
 +              }
  
 -                      if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
 -                              DEBUG ("%s (%p, %u): sem_timedwait failure: %s", 
 -                                      __func__, handle, timeout, g_strerror (errno));
 -                              /* Should we return a failure here? */
 -                      }
 +              if (ret == -1 && errno != EINTR && errno != ETIMEDOUT) {
 +                      DEBUG ("%s (%p, %u): sem_timedwait failure: %s", 
 +                                 __func__, handle, timeout, g_strerror (errno));
 +                      /* Should we return a failure here? */
 +              }
  
 -                      if (ret == 0) {
 -                              /* Success, process has exited */
 -                              MONO_SEM_POST (&mp->exit_sem);
 -                              break;
 -                      }
 -              } else {
 -                      /* We did not create this process, so we can't waidpid / sem_wait it.
 -                       * We need to poll for the pid existence */
 -                      DEBUG ("%s (%p, %u): polling on pid...", __func__, handle, timeout);
 -                      if (!is_pid_valid (pid)) {
 -                              /* Success, process has exited */
 -                              break;
 -                      }
 +              if (ret == 0) {
 +                      /* Success, process has exited */
 +                      MONO_SEM_POST (&mp->exit_sem);
 +                      break;
                }
  
                if (timeout == 0) {
                        DEBUG ("%s (%p, %u): WAIT_TIMEOUT", __func__, handle, timeout);
                        return WAIT_TIMEOUT;
                }
 -
 -              if (spin) {
 -                      /* "timeout - (now - start)" will not underflow, since timeout is always >=0,
 -                       * and we passed the check just above */
 -                      _wapi_handle_spin (MIN (100, timeout - (now - start)));
 -              }
                
 -              if (alertable && _wapi_thread_apc_pending (current_thread)) {
 +              if (alertable && _wapi_thread_cur_apc_pending ()) {
                        DEBUG ("%s (%p, %u): WAIT_IO_COMPLETION", __func__, handle, timeout);
                        return WAIT_IO_COMPLETION;
                }
        g_assert (ret == 0);
  
        status = mp ? mp->status : 0;
 -      if (WIFSIGNALED (status)) {
 +      if (WIFSIGNALED (status))
                process_handle->exitstatus = 128 + WTERMSIG (status);
 -      } else {
 +      else
                process_handle->exitstatus = WEXITSTATUS (status);
 -      }
        _wapi_time_t_to_filetime (time (NULL), &process_handle->exit_time);
  
        process_handle->exited = TRUE;
        DEBUG ("%s (%p, %u): Setting pid %d signalled, exit status %d",
                   __func__, handle, timeout, process_handle->id, process_handle->exitstatus);
  
 -      _wapi_shared_handle_set_signal_state (handle, TRUE);
 +      _wapi_handle_set_signal_state (handle, TRUE, TRUE);
  
        _wapi_handle_unlock_shared_handles ();
  
diff --combined mono/tests/Makefile.am
index b215ab65709937cf5d75db2691ae0356bef2e7a6,38d490666661161a5eb2c2c3f050c5c331442ec6..9c6ebbaa1245c658e8e06f5fa9d0907e9f7fc85e
@@@ -43,7 -43,6 +43,7 @@@ STRESS_TESTS_SRC=     
        monitor-stress.cs       \
        thread-stress.cs        \
        gc-stress.cs            \
 +      gc-copy-stress.cs       \
        gc-graystack-stress.cs          \
        exit-stress.cs          \
        process-stress.cs       \
@@@ -214,7 -213,6 +214,7 @@@ BASE_TEST_CS_SRC=          
        array3.cs               \
        classinit.cs            \
        classinit2.cs           \
 +      classinit3.cs           \
        synchronized.cs         \
        async_read.cs           \
        threadpool.cs           \
        bug-599469.cs   \
        bug-389886-3.cs \
        monitor.cs      \
 +      monitor-resurrection.cs \
        dynamic-method-resurrection.cs  \
        bug-666008.cs   \
        bug-685908.cs   \
        unload-appdomain-on-shutdown.cs \
        block_guard_restore_aligment_on_exit.cs \
        thread_static_gc_layout.cs \
-       sleep.cs
+       sleep.cs \
+       bug-17537.cs
  
  TEST_CS_SRC_DIST=     \
        $(BASE_TEST_CS_SRC)     \
@@@ -438,8 -436,7 +439,8 @@@ endi
  if X86
  
  if HOST_WIN32
 -PLATFORM_DISABLED_TESTS=async-exc-compilation.exe finally_guard.exe finally_block_ending_in_dead_bb.exe
 +PLATFORM_DISABLED_TESTS=async-exc-compilation.exe finally_guard.exe finally_block_ending_in_dead_bb.exe \
 +      bug-18026.exe monitor.exe threadpool-exceptions5.exe
  endif
  
  endif
@@@ -938,11 -935,13 +939,11 @@@ SGEN_TESTS =    
  
  SGEN_CONFIGURATIONS = \
        "|plain"        \
 -      "major=marksweep-par|ms-par"    \
        "major=marksweep-conc|ms-conc"  \
        "major=marksweep-conc,minor=split|ms-conc-split"        \
        "minor=split|ms-split"  \
        "minor=split,alloc-ratio=95|ms-split-95"        \
        "|plain-clear-at-gc|clear-at-gc"        \
 -      "major=marksweep-par|ms-par-clear-at-gc|clear-at-gc"    \
        "major=marksweep-conc|ms-conc-clear-at-gc|clear-at-gc"  \
        "minor=split|ms-split-clear-at-gc|clear-at-gc"
  
@@@ -1190,6 -1189,14 +1191,14 @@@ bug-382986-lib.dll: bug-382986-lib.c
  bug-382986.exe: bug-382986.cs bug-382986-lib.dll
        $(MCS) -out:$@ -r:bug-382986-lib.dll $(srcdir)/bug-382986.cs
  
+ EXTRA_DIST += bug-17537-helper.cs
+ bug-17537-helper.exe: bug-17537-helper.cs
+       $(MCS) -out:$@ $(srcdir)/bug-17537-helper.cs
+       chmod -x $@
+ bug-17537.exe: bug-17537.cs bug-17537-helper.exe
+       $(MCS) -out:$@ $(srcdir)/bug-17537.cs
  EXTRA_DIST += coreclr-security.cs
  
  coreclr-security.exe : coreclr-security.cs
@@@ -1301,8 -1308,12 +1310,8 @@@ patch-libtool
  if NACL_CODEGEN
  test-process-exit:
  else
 -EXTRA_DIST += bug-438454.cs bug-438454.exe.stdout.expected threadpool-in-processexit.cs threadpool-in-processexit.exe.stdout.expected
 +EXTRA_DIST += threadpool-in-processexit.cs threadpool-in-processexit.exe.stdout.expected
  test-process-exit:
 -      @$(MCS) $(srcdir)/bug-438454.cs -out:bug-438454.exe
 -      @echo "Testing bug-438454.exe..."
 -      @$(RUNTIME) bug-438454.exe > bug-438454.exe.stdout
 -      @diff -w bug-438454.exe.stdout $(srcdir)/bug-438454.exe.stdout.expected
        @$(MCS) $(srcdir)/threadpool-in-processexit.cs -out:threadpool-in-processexit.exe
        @echo "Testing threadpool-in-processexit.exe..."
        @$(RUNTIME) threadpool-in-processexit.exe > threadpool-in-processexit.exe.stdout
@@@ -1317,6 -1328,7 +1326,6 @@@ OOM_TESTS =     
  test-oom: $(OOM_TESTS)
        @for fn in $+ ; do      \
                echo "Testing $$fn ...";        \
 -              MONO_GC_PARAMS=max-heap-size=16m,major=marksweep-par MONO_ENV_OPTIONS="--gc=sgen" $(RUNTIME) $$fn > $$fn.stdout || exit 1;      \
                MONO_GC_PARAMS=max-heap-size=16m MONO_ENV_OPTIONS="--gc=sgen"                     $(RUNTIME) $$fn > $$fn.stdout || exit 1;      \
                MONO_GC_PARAMS=max-heap-size=16m                                                  $(RUNTIME) $$fn > $$fn.stdout || exit 1;      \
        done