X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fio-layer%2Fprocesses.c;h=cc25304b2708667097150eab976200dc907c3789;hb=b7363be6673f10904d63fade7ed104bc01a46da9;hp=105c2dbb75db9647d532a51c888526fff79b0a38;hpb=107ea208bdc65f58942721c6bb3f69e7a02a4a26;p=mono.git diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c index 105c2dbb75d..cc25304b270 100644 --- a/mono/io-layer/processes.c +++ b/mono/io-layer/processes.c @@ -4,7 +4,7 @@ * Author: * Dick Porter (dick@ximian.com) * - * (C) 2002 Ximian, Inc. + * (C) 2002-2006 Novell, Inc. */ #include @@ -41,7 +41,8 @@ struct _WapiHandleOps _wapi_process_ops = { NULL, /* signal */ NULL, /* own */ NULL, /* is_owned */ - process_wait /* special_wait */ + process_wait, /* special_wait */ + NULL /* prewait */ }; static mono_once_t process_current_once=MONO_ONCE_INIT; @@ -140,7 +141,8 @@ void _wapi_process_reap (void) g_message ("%s: Reaping child processes", __func__); #endif - _wapi_search_handle (WAPI_HANDLE_PROCESS, waitfor_pid, NULL, NULL); + _wapi_search_handle (WAPI_HANDLE_PROCESS, waitfor_pid, NULL, NULL, + FALSE); } /* Limitations: This can only wait for processes that are our own @@ -216,6 +218,14 @@ static guint32 process_wait (gpointer handle, guint32 timeout) return(WAIT_OBJECT_0); } + +void _wapi_process_signal_self () +{ + if (current_process != NULL) { + process_set_termination_details (current_process, 0); + } +} + static void process_set_defaults (struct _WapiHandle_process *process_handle) { @@ -241,6 +251,11 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) SetLastError (ERROR_INVALID_PARAMETER); return (FALSE); } + + if (sei->lpFile == NULL) { + /* w2k returns TRUE for this, for some reason. */ + return (TRUE); + } /* Put both executable and parameters into the second argument * to CreateProcess (), so it searches $PATH. The conversion @@ -253,27 +268,31 @@ gboolean ShellExecuteEx (WapiShellExecuteInfo *sei) return (FALSE); } - u8params = g_utf16_to_utf8 (sei->lpParameters, -1, NULL, NULL, NULL); - if (u8params == NULL) { - SetLastError (ERROR_INVALID_DATA); - g_free (u8file); - return (FALSE); - } + if (sei->lpParameters != NULL) { + u8params = g_utf16_to_utf8 (sei->lpParameters, -1, NULL, NULL, NULL); + if (u8params == NULL) { + SetLastError (ERROR_INVALID_DATA); + g_free (u8file); + return (FALSE); + } - u8args = g_strdup_printf ("%s %s", u8file, u8params); - if (u8args == NULL) { - SetLastError (ERROR_INVALID_DATA); - g_free (u8params); - g_free (u8file); - return (FALSE); - } + u8args = g_strdup_printf ("%s %s", u8file, u8params); + if (u8args == NULL) { + SetLastError (ERROR_INVALID_DATA); + g_free (u8params); + g_free (u8file); + return (FALSE); + } - args = g_utf8_to_utf16 (u8args, -1, NULL, NULL, NULL); + args = g_utf8_to_utf16 (u8args, -1, NULL, NULL, NULL); - g_free (u8file); - g_free (u8params); - g_free (u8args); - + g_free (u8file); + g_free (u8params); + g_free (u8args); + } else { + args = g_utf8_to_utf16 (u8file, -1, NULL, NULL, NULL); + } + if (args == NULL) { SetLastError (ERROR_INVALID_DATA); return (FALSE); @@ -313,7 +332,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, GError *gerr = NULL; int in_fd, out_fd, err_fd; pid_t pid; - int lockpipe [2]; int thr_ret; mono_once (&process_ops_once, process_ops_init); @@ -622,6 +640,11 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, SetLastError (ERROR_PATH_NOT_FOUND); goto cleanup; } + + /* Hold another reference so the process has somewhere to + * store its exit data even if we drop this handle + */ + _wapi_handle_ref (handle); /* new_environ is a block of NULL-terminated strings, which * is itself NULL-terminated. Of course, passing an array of @@ -693,8 +716,9 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, env_strings[env_count] = g_strdup_printf ("_WAPI_PROCESS_HANDLE_OFFSET=%d", ref->offset); } - - pipe (lockpipe); + + thr_ret = _wapi_handle_lock_shared_handles (); + g_assert (thr_ret == 0); pid = fork (); if (pid == -1) { @@ -704,13 +728,16 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, goto cleanup; } else if (pid == 0) { /* Child */ - char c [1]; - /* Wait for the parent to finish setting up the handle */ - close (lockpipe [1]); - while (read (lockpipe [0], c, 1) == -1 && - errno == EINTR); - close (lockpipe [0]); + /* Wait for the parent to finish setting up the + * handle. The semaphore lock is safe because the + * sem_undo structures of a semaphore aren't inherited + * across a fork () + */ + thr_ret = _wapi_handle_lock_shared_handles (); + g_assert (thr_ret == 0); + + _wapi_handle_unlock_shared_handles (); /* should we detach from the process group? */ @@ -753,9 +780,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, exit (-1); } /* parent */ - - thr_ret = _wapi_handle_lock_shared_handles (); - g_assert (thr_ret == 0); ret = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, (gpointer *)&process_handle_data); @@ -768,10 +792,6 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, process_handle_data->id = pid; - _wapi_handle_unlock_shared_handles (); - - write (lockpipe [1], cmd, 1); - if (process_info != NULL) { process_info->hProcess = handle; process_info->dwProcessId = pid; @@ -784,9 +804,8 @@ gboolean CreateProcess (const gunichar2 *appname, const gunichar2 *cmdline, } cleanup: - close (lockpipe [0]); - close (lockpipe [1]); - + _wapi_handle_unlock_shared_handles (); + if (cmd != NULL) { g_free (cmd); } @@ -833,13 +852,20 @@ static void process_set_name (struct _WapiHandle_process *process_handle) 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) { - pid_t pid = getpid (); - char *handle_env; + pid_t pid = _wapi_getpid (); + const char *handle_env; struct _WapiHandle_process process_handle = {0}; - handle_env = getenv ("_WAPI_PROCESS_HANDLE_OFFSET"); + handle_env = g_getenv ("_WAPI_PROCESS_HANDLE_OFFSET"); + g_unsetenv ("_WAPI_PROCESS_HANDLE_OFFSET"); + if (handle_env != NULL) { struct _WapiHandle_process *process_handlep; guchar *procname = NULL; @@ -848,48 +874,50 @@ static void process_set_current (void) current_process = _wapi_handle_new_from_offset (WAPI_HANDLE_PROCESS, atoi (handle_env), TRUE); #ifdef DEBUG - g_message ("%s: Found my process handle: %p (offset %d)", - __func__, current_process, atoi (handle_env)); + g_message ("%s: Found my process handle: %p (offset %d 0x%x)", + __func__, current_process, atoi (handle_env), + atoi (handle_env)); #endif ok = _wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS, (gpointer *)&process_handlep); - if (ok == FALSE) { - g_warning ("%s: error looking up process handle %p", - __func__, current_process); - return; - } - - /* This test will 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 */ + 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 */ #ifdef DEBUG - g_message ("%s: Setting better process name", - __func__); + g_message ("%s: Setting better process name", __func__); #endif - - process_set_name (process_handlep); - } else { + + process_set_name (process_handlep); + } else { #ifdef DEBUG - g_message ("%s: Leaving process name: %s", - __func__, procname); + g_message ("%s: Leaving process name: %s", __func__, procname); #endif + } + + return; } - return; + /* Wrong pid, so drop this handle and fall through to + * create a new one + */ + _wapi_handle_unref (current_process); } - - /* 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.) + */ + #ifdef DEBUG g_message ("%s: Need to create my own process handle", __func__); #endif @@ -920,26 +948,26 @@ gpointer GetCurrentProcess (void) return((gpointer)-1); } -guint32 GetCurrentProcessId (void) +guint32 GetProcessId (gpointer handle) { - struct _WapiHandle_process *current_process_handle; + struct _WapiHandle_process *process_handle; gboolean ok; - mono_once (&process_current_once, process_set_current); - - ok=_wapi_lookup_handle (current_process, WAPI_HANDLE_PROCESS, - (gpointer *)¤t_process_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up current process handle %p", - __func__, current_process); - /* No failure return is defined. PID 0 is invalid. - * This should only be reached when something else has - * gone badly wrong anyway. - */ - return(0); + ok = _wapi_lookup_handle (handle, WAPI_HANDLE_PROCESS, + (gpointer *)&process_handle); + if (ok == FALSE) { + SetLastError (ERROR_INVALID_HANDLE); + return (0); } - return(current_process_handle->id); + return (process_handle->id); +} + +guint32 GetCurrentProcessId (void) +{ + mono_once (&process_current_once, process_set_current); + + return (GetProcessId (current_process)); } /* Returns the process id as a convenience to the functions that call this */ @@ -1025,7 +1053,7 @@ gboolean EnumProcesses (guint32 *pids, guint32 len, guint32 *needed) mono_once (&process_current_once, process_set_current); _wapi_search_handle (WAPI_HANDLE_PROCESS, process_enum, processes, - NULL); + NULL, TRUE); fit=len/sizeof(guint32); for (i = 0, j = 0; j < fit && i < processes->len; i++) { @@ -1079,7 +1107,7 @@ gpointer OpenProcess (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUS handle = _wapi_search_handle (WAPI_HANDLE_PROCESS, process_open_compare, - GUINT_TO_POINTER (pid), NULL); + GUINT_TO_POINTER (pid), NULL, TRUE); if (handle == 0) { #ifdef DEBUG g_message ("%s: Can't find pid %d", __func__, pid);