#include <mono/metadata/exception.h>
#include <mono/io-layer/io-layer.h>
#include <mono/metadata/w32handle.h>
+#include <mono/metadata/w32file.h>
#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/strenc.h>
+#include <mono/utils/mono-io-portability.h>
#ifndef MAXPATHLEN
#define MAXPATHLEN 242
} ProcessTime;
/*
- * MonoProcess describes processes we create.
+ * Process describes processes we create.
* It contains a semaphore that can be waited on in order to wait
* for process termination. It's accessed in our SIGCHLD handler,
* when status is updated (and pid cleared, to not clash with
* subsequent processes that may get executed).
*/
-typedef struct _MonoProcess MonoProcess;
-struct _MonoProcess {
+typedef struct _Process {
pid_t pid; /* the pid of the process. This value is only valid until the process has exited. */
MonoSemType exit_sem; /* this semaphore will be released when the process exits */
int status; /* the exit status */
- gint32 handle_count; /* the number of handles to this mono_process instance */
+ gint32 handle_count; /* the number of handles to this process instance */
/* we keep a ref to the creating _WapiHandle_process handle until
* the process has exited, so that the information there isn't lost.
*/
gpointer handle;
gboolean freeable;
- MonoProcess *next;
-};
+ gboolean signalled;
+ struct _Process *next;
+} Process;
/* MonoW32HandleProcess is a structure containing all the required information for process handling. */
typedef struct {
- pid_t id;
+ pid_t pid;
guint32 exitstatus;
gpointer main_thread;
guint64 create_time;
guint64 exit_time;
- char *proc_name;
+ char *pname;
size_t min_working_set;
size_t max_working_set;
gboolean exited;
- MonoProcess *mono_process;
+ Process *process;
} MonoW32HandleProcess;
/*
* We also need to lock when adding and cleaning up so that those two
* operations don't mess with eachother. (This lock is not used in the
* signal handler) */
-static MonoProcess *processes;
+static Process *processes;
static mono_mutex_t processes_mutex;
static gpointer current_process;
process_details (gpointer data)
{
MonoW32HandleProcess *process_handle = (MonoW32HandleProcess *) data;
- g_print ("id: %d, exited: %s, exitstatus: %d",
- process_handle->id, process_handle->exited ? "true" : "false", process_handle->exitstatus);
+ g_print ("pid: %d, exited: %s, exitstatus: %d",
+ process_handle->pid, process_handle->exited ? "true" : "false", process_handle->exitstatus);
}
static const gchar*
pid_t pid G_GNUC_UNUSED, ret;
int status;
gint64 start, now;
- MonoProcess *mp;
+ Process *process;
gboolean res;
/* FIXME: We can now easily wait on processes that aren't our own children,
return MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
}
- pid = process_handle->id;
+ pid = process_handle->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 processes here, the entry
* has a handle_count > 0 which means it will not be freed. */
- mp = process_handle->mono_process;
- if (!mp) {
+ process = process_handle->process;
+ if (!process) {
pid_t res;
if (pid == mono_process_current_pid ()) {
if (timeout != MONO_INFINITE_WAIT) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on semaphore for %li ms...",
__func__, handle, timeout, (long)(timeout - (now - start)));
- ret = mono_os_sem_timedwait (&mp->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ ret = mono_os_sem_timedwait (&process->exit_sem, (timeout - (now - start)), alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
} else {
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, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
+ ret = mono_os_sem_wait (&process->exit_sem, alerted ? MONO_SEM_FLAGS_ALERTABLE : MONO_SEM_FLAGS_NONE);
}
if (ret == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
/* Success, process has exited */
- mono_os_sem_post (&mp->exit_sem);
+ mono_os_sem_post (&process->exit_sem);
break;
}
/* Process must have exited */
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): Waited successfully", __func__, handle, timeout);
- status = mp->status;
+ status = process->status;
if (WIFSIGNALED (status))
process_handle->exitstatus = 128 + WTERMSIG (status);
else
process_handle->exited = TRUE;
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);
+ __func__, handle, timeout, process_handle->pid, process_handle->exitstatus);
mono_w32handle_set_signal_state (handle, TRUE, TRUE);
processes_cleanup (void)
{
static gint32 cleaning_up;
- MonoProcess *mp;
- MonoProcess *prev = NULL;
+ Process *process;
+ Process *prev = NULL;
GSList *finished = NULL;
GSList *l;
- gpointer unref_handle;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
if (InterlockedCompareExchange (&cleaning_up, 1, 0) != 0)
return;
- for (mp = processes; mp; mp = mp->next) {
- if (mp->pid == 0 && mp->handle) {
+ for (process = processes; process; process = process->next) {
+ if (process->signalled && process->handle) {
/* This process has exited and we need to remove the artifical ref
* on the handle */
- mono_os_mutex_lock (&processes_mutex);
- unref_handle = mp->handle;
- mp->handle = NULL;
- mono_os_mutex_unlock (&processes_mutex);
- if (unref_handle)
- mono_w32handle_unref (unref_handle);
+ mono_w32handle_unref (process->handle);
+ process->handle = NULL;
}
}
*/
mono_os_mutex_lock (&processes_mutex);
- mp = processes;
- while (mp) {
- if (mp->handle_count == 0 && mp->freeable) {
+ for (process = processes; process; process = process->next) {
+ if (process->handle_count == 0 && process->freeable) {
/*
* Unlink the entry.
* This code can run parallel with the sigchld handler, but the
* modifications it makes are safe.
*/
- if (mp == processes)
- processes = mp->next;
+ if (process == processes)
+ processes = process->next;
else
- prev->next = mp->next;
- finished = g_slist_prepend (finished, mp);
-
- mp = mp->next;
+ prev->next = process->next;
+ finished = g_slist_prepend (finished, process);
} else {
- prev = mp;
- mp = mp->next;
+ prev = process;
}
}
* they have the 'finished' flag set, which means the sigchld handler is done
* accessing them.
*/
- mp = (MonoProcess *)l->data;
- mono_os_sem_destroy (&mp->exit_sem);
- g_free (mp);
+ process = (Process *)l->data;
+ mono_os_sem_destroy (&process->exit_sem);
+ g_free (process);
}
g_slist_free (finished);
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s", __func__);
process_handle = (MonoW32HandleProcess *) data;
- g_free (process_handle->proc_name);
- process_handle->proc_name = NULL;
- if (process_handle->mono_process)
- InterlockedDecrement (&process_handle->mono_process->handle_count);
+ g_free (process_handle->pname);
+ process_handle->pname = NULL;
+ if (process_handle->process)
+ InterlockedDecrement (&process_handle->process->handle_count);
processes_cleanup ();
}
if (utf8_progname) {
slash = strrchr (utf8_progname, '/');
if (slash)
- process_handle->proc_name = g_strdup (slash+1);
+ process_handle->pname = g_strdup (slash+1);
else
- process_handle->proc_name = g_strdup (utf8_progname);
+ process_handle->pname = g_strdup (utf8_progname);
g_free (utf8_progname);
}
}
(MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
memset (&process_handle, 0, sizeof (process_handle));
- process_handle.id = wapi_getpid ();
+ process_handle.pid = wapi_getpid ();
process_set_defaults (&process_handle);
process_set_name (&process_handle);
return 0;
}
- return process_handle->id;
+ return process_handle->pid;
}
typedef struct {
process_handle = (MonoW32HandleProcess*) handle_specific;
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%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->pid);
- pid = process_handle->id;
+ pid = process_handle->pid;
if (pid == 0)
return FALSE;
guint32 count, avail = size / sizeof(gpointer);
int i;
pid_t pid;
- char *proc_name = NULL;
+ char *pname = NULL;
gboolean res;
/* Store modules in an array of pointers (main module as
if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
pid = WAPI_HANDLE_TO_PID (process);
- proc_name = mono_w32process_get_name (pid);
+ pname = mono_w32process_get_name (pid);
} else {
res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
return FALSE;
}
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
}
- if (!proc_name) {
+ if (!pname) {
modules[0] = NULL;
*needed = sizeof(gpointer);
return TRUE;
if (!mods) {
modules[0] = NULL;
*needed = sizeof(gpointer);
- g_free (proc_name);
+ g_free (pname);
return TRUE;
}
module = (MonoW32ProcessModule *)mods_iter->data;
if (modules[0] != NULL)
modules[i] = module->address_start;
- else if (match_procname_to_modulename (proc_name, module->filename))
+ else if (match_procname_to_modulename (pname, module->filename))
modules[0] = module->address_start;
else
modules[i + 1] = module->address_start;
*needed = sizeof(gpointer) * (count + 1);
g_slist_free (mods);
- g_free (proc_name);
+ g_free (pname);
return TRUE;
}
gsize bytes;
GSList *mods = NULL, *mods_iter;
MonoW32ProcessModule *found_module;
- char *proc_name = NULL;
+ char *pname = NULL;
gboolean res;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module base name, process handle %p module %p",
if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
/* This is a pseudo handle */
pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = mono_w32process_get_name (pid);
+ pname = mono_w32process_get_name (pid);
} else {
res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
return 0;
}
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
}
mods = mono_w32process_get_modules (pid);
if (!mods) {
- g_free (proc_name);
+ g_free (pname);
return 0;
}
for (mods_iter = mods; mods_iter; mods_iter = g_slist_next (mods_iter)) {
found_module = (MonoW32ProcessModule *)mods_iter->data;
if (procname_ext == NULL &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ ((module == NULL && match_procname_to_modulename (pname, found_module->filename)) ||
(module != NULL && found_module->address_start == module))) {
procname_ext = g_path_get_basename (found_module->filename);
}
}
g_slist_free (mods);
- g_free (proc_name);
+ g_free (pname);
if (procname_ext) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Process name is [%s]", __func__,
GSList *mods = NULL, *mods_iter;
MonoW32ProcessModule *found_module;
gboolean ret = FALSE;
- char *proc_name = NULL;
+ char *pname = NULL;
gboolean res;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Getting module info, process handle %p module %p",
if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- proc_name = mono_w32process_get_name (pid);
+ pname = mono_w32process_get_name (pid);
} else {
res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
return FALSE;
}
- pid = process_handle->id;
- proc_name = g_strdup (process_handle->proc_name);
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
}
mods = mono_w32process_get_modules (pid);
if (!mods) {
- g_free (proc_name);
+ g_free (pname);
return FALSE;
}
for (mods_iter = mods; mods_iter; mods_iter = g_slist_next (mods_iter)) {
found_module = (MonoW32ProcessModule *)mods_iter->data;
if (ret == FALSE &&
- ((module == NULL && match_procname_to_modulename (proc_name, found_module->filename)) ||
+ ((module == NULL && match_procname_to_modulename (pname, 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);
}
g_slist_free (mods);
- g_free (proc_name);
+ g_free (pname);
return ret;
}
{
int status;
int pid;
- MonoProcess *p;
+ Process *process;
do {
do {
/*
* This can run concurrently with the code in the rest of this module.
*/
- for (p = processes; p; p = p->next) {
- if (p->pid != pid)
+ for (process = processes; process; process = process->next) {
+ if (process->pid != pid)
+ continue;
+ if (process->signalled)
continue;
- p->pid = 0; /* this pid doesn't exist anymore, clear it */
- p->status = status;
- mono_os_sem_post (&p->exit_sem);
+ process->signalled = TRUE;
+ process->status = status;
+ mono_os_sem_post (&process->exit_sem);
mono_memory_barrier ();
/* Mark this as freeable, the pointer becomes invalid afterwards */
- p->freeable = TRUE;
+ process->freeable = TRUE;
break;
}
} while (1);
}
static gboolean
-process_create (const gunichar2 *appname, const gunichar2 *cmdline, gpointer new_environ,
+process_create (const gunichar2 *appname, const gunichar2 *cmdline,
const gunichar2 *cwd, StartupHandles *startup_handles, MonoW32ProcessInfo *process_info)
{
#if defined (HAVE_FORK) && defined (HAVE_EXECVE)
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;
+ guint32 i;
gboolean ret = FALSE;
gpointer handle = NULL;
GError *gerr = NULL;
pid_t pid = 0;
int startup_pipe [2] = {-1, -1};
int dummy;
- MonoProcess *mono_process;
+ Process *process;
#if HAVE_SIGACTION
mono_lazy_initialize (&process_sig_chld_once, process_add_sigchld_handler);
g_free (newapp);
if (newcmd) {
- ret = process_create (NULL, newcmd, new_environ, cwd, startup_handles, process_info);
+ ret = process_create (NULL, newcmd, cwd, startup_handles, process_info);
g_free (newcmd);
out_fd = GPOINTER_TO_UINT (startup_handles->output);
err_fd = GPOINTER_TO_UINT (startup_handles->error);
} else {
- in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
- out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
- err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
+ in_fd = GPOINTER_TO_UINT (mono_w32file_get_console_input ());
+ out_fd = GPOINTER_TO_UINT (mono_w32file_get_console_output ());
+ err_fd = GPOINTER_TO_UINT (mono_w32file_get_console_error ());
}
- /* new_environ is a block of NULL-terminated strings, which
- * is itself NULL-terminated. Of course, passing an array of
- * string pointers would have made things too easy :-(
+ /*
+ * process->env_variables is a an array of MonoString*
*
* If new_environ is not NULL it specifies the entire set of
* environment variables in the new process. Otherwise the
* new process inherits the same environment.
*/
- if (new_environ) {
- gunichar2 *new_environp;
+ if (process_info->env_variables) {
+ gint i, str_length, var_length;
+ MonoString *var;
+ gunichar2 *str;
- /* Count the number of strings */
- for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
- env_count++;
- while (*new_environp)
- new_environp++;
- }
+ /* +2: one for the process handle value, and the last one is NULL */
+ env_strings = g_new0 (gchar*, mono_array_length (process_info->env_variables) + 2);
- /* +2: one for the process handle value, and the last
- * one is NULL
- */
- env_strings = g_new0 (char *, env_count + 2);
+ str = NULL;
+ str_length = 0;
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (new_environp = (gunichar2 *)new_environ; *new_environp; new_environp++) {
- env_strings[env_count] = mono_unicode_to_external (new_environp);
- env_count++;
- while (*new_environp) {
- new_environp++;
+ /* Copy each environ string into 'strings' turning it into utf8 (or the requested encoding) at the same time */
+ for (i = 0; i < mono_array_length (process_info->env_variables); ++i) {
+ var = mono_array_get (process_info->env_variables, MonoString*, i);
+ var_length = mono_string_length (var);
+
+ /* str is a null-terminated copy of var */
+
+ if (var_length + 1 > str_length) {
+ str_length = var_length + 1;
+ str = g_renew (gunichar2, str, str_length);
}
+
+ memcpy (str, mono_string_chars (var), var_length * sizeof (gunichar2));
+ str [var_length] = '\0';
+
+ env_strings [i] = mono_unicode_to_external (str);
}
+
+ g_free (str);
} else {
+ guint32 env_count;
+
+ env_count = 0;
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 (char *, env_count + 2);
+ /* +2: one for the process handle value, and the last one is NULL */
+ env_strings = g_new0 (gchar*, env_count + 2);
- /* Copy each environ string into 'strings' turning it
- * into utf8 (or the requested encoding) at the same
- * time
- */
- env_count = 0;
- for (i = 0; environ[i] != NULL; i++) {
- env_strings[env_count] = g_strdup (environ[i]);
- env_count++;
- }
+ /* Copy each environ string into 'strings' turning it into utf8 (or the requested encoding) at the same time */
+ for (i = 0; i < env_count; i++)
+ env_strings [i] = g_strdup (environ[i]);
}
/* Create a pipe to make sure the child doesn't exit before
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__);
}
-#if HAVE_SIGACTION
- /* FIXME: block SIGCHLD */
-#endif
-
switch (pid = fork ()) {
case -1: /* Error */ {
SetLastError (ERROR_OUTOFMEMORY);
MonoW32HandleProcess process_handle;
memset (&process_handle, 0, sizeof (process_handle));
- process_handle.id = pid;
- process_handle.proc_name = g_strdup (prog);
+ process_handle.pid = pid;
+ process_handle.pname = g_strdup (prog);
process_set_defaults (&process_handle);
- /* Add our mono_process into the linked list of processes */
- mono_process = (MonoProcess *) g_malloc0 (sizeof (MonoProcess));
- mono_process->pid = pid;
- mono_process->handle_count = 1;
- mono_os_sem_init (&mono_process->exit_sem, 0);
+ /* Add our process into the linked list of processes */
+ process = (Process *) g_malloc0 (sizeof (Process));
+ process->pid = pid;
+ process->handle_count = 1;
+ mono_os_sem_init (&process->exit_sem, 0);
- process_handle.mono_process = mono_process;
+ process_handle.process = process;
handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating process handle", __func__);
- mono_os_sem_destroy (&mono_process->exit_sem);
- g_free (mono_process);
+ mono_os_sem_destroy (&process->exit_sem);
+ g_free (process);
SetLastError (ERROR_OUTOFMEMORY);
ret = FALSE;
/* Keep the process handle artificially alive until the process
* exits so that the information in the handle isn't lost. */
mono_w32handle_ref (handle);
- mono_process->handle = handle;
+ process->handle = handle;
mono_os_mutex_lock (&processes_mutex);
- mono_process->next = processes;
- processes = mono_process;
+ process->next = processes;
+ mono_memory_barrier ();
+ processes = process;
mono_os_mutex_unlock (&processes_mutex);
if (process_info != NULL) {
}
}
-#if HAVE_SIGACTION
- /* FIXME: unblock SIGCHLD */
-#endif
-
if (startup_pipe [1] != -1) {
/* Write 1 byte, doesn't matter what */
ssize_t _i G_GNUC_UNUSED = write (startup_pipe [1], startup_pipe, 1);
ret = FALSE;
goto done;
}
- ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ ret = process_create (NULL, args, lpDirectory, NULL, process_info);
g_free (args);
if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
ret = FALSE;
goto done;
}
- ret = process_create (NULL, args, NULL, lpDirectory, NULL, process_info);
+ ret = process_create (NULL, args, lpDirectory, NULL, process_info);
g_free (args);
if (!ret) {
if (GetLastError () != ERROR_OUTOFMEMORY)
}
static gboolean
-process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path, MonoString **cmd)
+process_get_shell_arguments (MonoW32ProcessStartInfo *proc_start_info, gunichar2 **shell_path)
{
- gchar *spath = NULL;
+ gchar *complete_path = NULL;
*shell_path = NULL;
- *cmd = proc_start_info->arguments;
- process_get_complete_path (mono_string_chars (proc_start_info->filename), &spath);
- if (spath != NULL) {
- *shell_path = g_utf8_to_utf16 (spath, -1, NULL, NULL, NULL);
- g_free (spath);
+ if (process_get_complete_path (mono_string_chars (proc_start_info->filename), &complete_path)) {
+ *shell_path = g_utf8_to_utf16 (complete_path, -1, NULL, NULL, NULL);
+ g_free (complete_path);
}
- return (*shell_path != NULL) ? TRUE : FALSE;
+ return *shell_path != NULL;
}
MonoBoolean
gunichar2 *dir;
StartupHandles startup_handles;
gunichar2 *shell_path = NULL;
- gchar *env_vars = NULL;
- MonoString *cmd = NULL;
+ gunichar2 *args = NULL;
memset (&startup_handles, 0, sizeof (startup_handles));
startup_handles.input = stdin_handle;
startup_handles.output = stdout_handle;
startup_handles.error = stderr_handle;
- if (process_get_shell_arguments (proc_start_info, &shell_path, &cmd) == FALSE) {
+ if (!process_get_shell_arguments (proc_start_info, &shell_path)) {
process_info->pid = -ERROR_FILE_NOT_FOUND;
return FALSE;
}
- if (process_info->env_keys) {
- gint i, len;
- MonoString *ms;
- MonoString *key, *value;
- gunichar2 *str, *ptr;
- gunichar2 *equals16;
-
- for (len = 0, i = 0; i < mono_array_length (process_info->env_keys); i++) {
- ms = mono_array_get (process_info->env_values, MonoString *, i);
- if (ms == NULL)
- continue;
-
- len += mono_string_length (ms) * sizeof (gunichar2);
- ms = mono_array_get (process_info->env_keys, MonoString *, i);
- len += mono_string_length (ms) * sizeof (gunichar2);
- len += 2 * sizeof (gunichar2);
- }
-
- equals16 = g_utf8_to_utf16 ("=", 1, NULL, NULL, NULL);
- ptr = str = g_new0 (gunichar2, len + 1);
- for (i = 0; i < mono_array_length (process_info->env_keys); i++) {
- value = mono_array_get (process_info->env_values, MonoString *, i);
- if (value == NULL)
- continue;
-
- key = mono_array_get (process_info->env_keys, MonoString *, i);
- memcpy (ptr, mono_string_chars (key), mono_string_length (key) * sizeof (gunichar2));
- ptr += mono_string_length (key);
-
- memcpy (ptr, equals16, sizeof (gunichar2));
- ptr++;
-
- memcpy (ptr, mono_string_chars (value), mono_string_length (value) * sizeof (gunichar2));
- ptr += mono_string_length (value);
- ptr++;
- }
+ args = proc_start_info->arguments && mono_string_length (proc_start_info->arguments) > 0 ?
+ mono_string_chars (proc_start_info->arguments): NULL;
- g_free (equals16);
- env_vars = (gchar *) str;
- }
-
/* The default dir name is "". Turn that into NULL to mean "current directory" */
dir = proc_start_info->working_directory && mono_string_length (proc_start_info->working_directory) > 0 ?
mono_string_chars (proc_start_info->working_directory) : NULL;
- ret = process_create (shell_path, cmd ? mono_string_chars (cmd): NULL, env_vars, dir, &startup_handles, process_info);
+ ret = process_create (shell_path, args, dir, &startup_handles, process_info);
- g_free (env_vars);
if (shell_path != NULL)
g_free (shell_path);
return FALSE;
}
- if (process_handle->id == wapi_getpid ()) {
+ if (process_handle->pid == wapi_getpid ()) {
*exitcode = STILL_ACTIVE;
return TRUE;
}
return FALSE;
}
- pid = process_handle->id;
+ pid = process_handle->pid;
}
ret = kill (pid, exitcode == -1 ? SIGKILL : SIGTERM);
return 0;
}
- pid = process_handle->id;
+ pid = process_handle->pid;
}
errno = 0;
return FALSE;
}
- pid = process_handle->id;
+ pid = process_handle->pid;
}
switch (priorityClass) {
ticks_to_processtime (process_handle->exit_time, exit_processtime);
#ifdef HAVE_GETRUSAGE
- if (process_handle->id == getpid ()) {
+ if (process_handle->pid == getpid ()) {
struct rusage time_data;
if (getrusage (RUSAGE_SELF, &time_data) == 0) {
ticks_to_processtime ((guint64)time_data.ru_utime.tv_sec * 10000000 + (guint64)time_data.ru_utime.tv_usec * 10, user_processtime);
return(NULL);
}
- fd = _wapi_open (filename_ext, O_RDONLY, 0);
- if (fd == -1) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename_ext, strerror (errno));
+ fd = open (filename_ext, O_RDONLY, 0);
+ if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno;
+ gchar *located_filename;
- SetLastError (_wapi_get_win32_file_error (errno));
- g_free (filename_ext);
+ saved_errno = errno;
- return(NULL);
+ located_filename = mono_portability_find_file (filename_ext, TRUE);
+ if (!located_filename) {
+ errno = saved_errno;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (1): %s", __func__, filename_ext, strerror (errno));
+
+ g_free (filename_ext);
+
+ SetLastError (_wapi_get_win32_file_error (errno));
+ return NULL;
+ }
+
+ fd = open (located_filename, O_RDONLY, 0);
+ if (fd == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (2): %s", __func__, filename_ext, strerror (errno));
+
+ g_free (filename_ext);
+ g_free (located_filename);
+
+ SetLastError (_wapi_get_win32_file_error (errno));
+ return NULL;
+ }
+
+ g_free (located_filename);
}
if (fstat (fd, &statbuf) == -1) {