extern char **environ;
#endif
-/*
- * Handles > _WAPI_PROCESS_UNHANDLED are pseudo handles which represent processes
- * not started by the runtime.
- */
-/* This marks a system process that we don't have a handle on */
-/* FIXME: Cope with PIDs > sizeof guint */
-#define _WAPI_PROCESS_UNHANDLED (1 << (8*sizeof(pid_t)-1))
-
-#define WAPI_IS_PSEUDO_PROCESS_HANDLE(handle) ((GPOINTER_TO_UINT(handle) & _WAPI_PROCESS_UNHANDLED) == _WAPI_PROCESS_UNHANDLED)
-#define WAPI_PID_TO_HANDLE(pid) GINT_TO_POINTER (_WAPI_PROCESS_UNHANDLED + (pid))
-#define WAPI_HANDLE_TO_PID(handle) (GPOINTER_TO_UINT ((handle)) - _WAPI_PROCESS_UNHANDLED)
-
typedef enum {
STARTF_USESHOWWINDOW=0x001,
STARTF_USESIZE=0x002,
/* MonoW32HandleProcess is a structure containing all the required information for process handling. */
typedef struct {
pid_t pid;
+ gboolean child;
guint32 exitstatus;
gpointer main_thread;
guint64 create_time;
static const gunichar2 utf16_quote_bytes [2] = { 0x22, 0 };
static const gunichar2 *utf16_quote = utf16_quote_bytes;
+/* Check if a pid is valid - i.e. if a process exists with this pid. */
+static gboolean
+process_is_alive (pid_t pid)
+{
+#if defined(HOST_WATCHOS)
+ return TRUE; // TODO: Rewrite using sysctl
+#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
+ if (pid == 0)
+ return FALSE;
+ if (kill (pid, 0) == 0)
+ return TRUE;
+ if (errno == EPERM)
+ return TRUE;
+ return FALSE;
+#elif defined(__HAIKU__)
+ team_info teamInfo;
+ if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
+ return TRUE;
+ return FALSE;
+#else
+ gchar *dir = g_strdup_printf ("/proc/%d", pid);
+ gboolean result = access (dir, F_OK) == 0;
+ g_free (dir);
+ return result;
+#endif
+}
+
static void
process_details (gpointer data)
{
Process *process;
gboolean res;
- /* FIXME: We can now easily wait on processes that aren't our own children,
- * but WaitFor*Object won't call us for pseudo handles. */
- g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
-
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u)", __func__, handle, timeout);
if (alerted)
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. */
- process = process_handle->process;
- if (!process) {
- pid_t res;
-
- if (pid == mono_process_current_pid ()) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
- return MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- }
+ if (pid == mono_process_current_pid ()) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on current process", __func__, handle, timeout);
+ return MONO_W32HANDLE_WAIT_RET_TIMEOUT;
+ }
- /* This path is used when calling Process.HasExited, so
- * it is only used to poll the state of the process, not
- * to actually wait on it to exit */
- g_assert (timeout == 0);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): PID: %d", __func__, handle, timeout, pid);
+ if (!process_handle->child) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): waiting on non-child process", __func__, handle, timeout);
- res = waitpid (pid, &status, WNOHANG);
- if (res == 0) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process wait timeout", __func__, handle, timeout);
- return MONO_W32HANDLE_WAIT_RET_TIMEOUT;
- }
- if (res > 0) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process waited successfully", __func__, handle, timeout);
+ if (!process_is_alive (pid)) {
+ /* assume the process has exited */
+ process_handle->exited = TRUE;
+ process_handle->exitstatus = -1;
+ mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s (%p, %u): non-child process is not alive anymore (2)", __func__, handle, timeout);
return MONO_W32HANDLE_WAIT_RET_SUCCESS_0;
}
return MONO_W32HANDLE_WAIT_RET_FAILED;
}
+ /* We don't need to lock processes here, the entry
+ * has a handle_count > 0 which means it will not be freed. */
+ process = process_handle->process;
+ g_assert (process);
+
start = mono_msec_ticks ();
now = start;
g_free (cli_launcher);
}
-/* Check if a pid is valid - i.e. if a process exists with this pid. */
-static gboolean
-is_pid_valid (pid_t pid)
-{
- gboolean result = FALSE;
-
-#if defined(HOST_WATCHOS)
- result = TRUE; // TODO: Rewrite using sysctl
-#elif defined(PLATFORM_MACOSX) || defined(__OpenBSD__) || defined(__FreeBSD__)
- if (((kill(pid, 0) == 0) || (errno == EPERM)) && pid != 0)
- result = TRUE;
-#elif defined(__HAIKU__)
- team_info teamInfo;
- if (get_team_info ((team_id)pid, &teamInfo) == B_OK)
- result = TRUE;
-#else
- char *dir = g_strdup_printf ("/proc/%d", pid);
- if (!access (dir, F_OK))
- result = TRUE;
- g_free (dir);
-#endif
-
- return result;
-}
-
static int
len16 (const gunichar2 *str)
{
MonoW32HandleProcess *process_handle;
gboolean res;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
- /* This is a pseudo handle */
- return WAPI_HANDLE_TO_PID (handle);
- }
-
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
mono_w32error_set_last (ERROR_INVALID_HANDLE);
if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_PROCESS)
return FALSE;
- g_assert (!WAPI_IS_PSEUDO_PROCESS_HANDLE (handle));
-
process_handle = (MonoW32HandleProcess*) handle_specific;
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking at process %d", __func__, process_handle->pid);
return handle;
}
- if (is_pid_valid (pid)) {
- /* Return a pseudo handle for processes we don't have handles for */
- return WAPI_PID_TO_HANDLE (pid);
+ if (process_is_alive (pid)) {
+ /* non-child process */
+ MonoW32HandleProcess process_handle;
+
+ memset (&process_handle, 0, sizeof (process_handle));
+ process_handle.pid = pid;
+ process_handle.pname = mono_w32process_get_name (pid);
+
+ handle = mono_w32handle_new (MONO_W32HANDLE_PROCESS, &process_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating process handle", __func__);
+
+ mono_w32error_set_last (ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ return handle;
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
if (size < sizeof(gpointer))
return FALSE;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = WAPI_HANDLE_TO_PID (process);
- pname = mono_w32process_get_name (pid);
- } else {
- res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
- return FALSE;
- }
-
- pid = process_handle->pid;
- pname = g_strdup (process_handle->pname);
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
}
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
+
if (!pname) {
modules[0] = NULL;
*needed = sizeof(gpointer);
if (basename == NULL || size == 0)
return 0;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- pname = mono_w32process_get_name (pid);
- } else {
- res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
- return 0;
- }
-
- pid = process_handle->pid;
- pname = g_strdup (process_handle->pname);
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return 0;
}
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
+
mods = mono_w32process_get_modules (pid);
if (!mods) {
g_free (pname);
if (modinfo == NULL || size < sizeof (MODULEINFO))
return FALSE;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (process)) {
- pid = (pid_t)WAPI_HANDLE_TO_PID (process);
- pname = mono_w32process_get_name (pid);
- } else {
- res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
- return FALSE;
- }
-
- pid = process_handle->pid;
- pname = g_strdup (process_handle->pname);
+ res = mono_w32handle_lookup (process, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, process);
+ return FALSE;
}
+ pid = process_handle->pid;
+ pname = g_strdup (process_handle->pname);
+
mods = mono_w32process_get_modules (pid);
if (!mods) {
g_free (pname);
memset (&process_handle, 0, sizeof (process_handle));
process_handle.pid = pid;
+ process_handle.child = TRUE;
process_handle.pname = g_strdup (prog);
process_set_defaults (&process_handle);
ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
{
MonoW32HandleProcess *process_handle;
- guint32 pid;
gboolean res;
if (!exitcode)
return FALSE;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
- pid = WAPI_HANDLE_TO_PID (handle);
- /* 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 */
- if (is_pid_valid (pid)) {
- *exitcode = STILL_ACTIVE;
- return TRUE;
- } else {
- *exitcode = -1;
- return TRUE;
- }
- }
-
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
MonoBoolean
ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
{
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- return TRUE;
return mono_w32handle_close (handle);
}
MonoW32HandleProcess *process_handle;
int ret;
pid_t pid;
+ gboolean res;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
- } else {
- gboolean res;
-
- res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
- mono_w32error_set_last (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- pid = process_handle->pid;
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return FALSE;
}
+ pid = process_handle->pid;
+
ret = kill (pid, exitcode == -1 ? SIGKILL : SIGTERM);
if (ret == 0)
return TRUE;
if (!min || !max)
return FALSE;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- return FALSE;
-
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
return FALSE;
}
+ if (!process_handle->child)
+ return FALSE;
+
*min = process_handle->min_working_set;
*max = process_handle->max_working_set;
return TRUE;
MonoW32HandleProcess *process_handle;
gboolean res;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
- return FALSE;
-
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
return FALSE;
}
+ if (!process_handle->child)
+ return FALSE;
+
process_handle->min_working_set = min;
process_handle->max_working_set = max;
return TRUE;
MonoW32HandleProcess *process_handle;
gint ret;
pid_t pid;
+ gboolean res;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
- } else {
- gboolean res;
-
- res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_w32error_set_last (ERROR_INVALID_HANDLE);
- return 0;
- }
-
- pid = process_handle->pid;
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return 0;
}
+ pid = process_handle->pid;
+
errno = 0;
ret = getpriority (PRIO_PROCESS, pid);
if (ret == -1 && errno != 0) {
int ret;
int prio;
pid_t pid;
+ gboolean res;
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
- /* This is a pseudo handle */
- pid = (pid_t)WAPI_HANDLE_TO_PID (handle);
- } else {
- gboolean res;
-
- res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_w32error_set_last (ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- pid = process_handle->pid;
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return FALSE;
}
+ pid = process_handle->pid;
+
switch (priorityClass) {
case MONO_W32PROCESS_PRIORITY_CLASS_IDLE:
prio = 19;
memset (kernel_processtime, 0, sizeof (ProcessTime));
memset (user_processtime, 0, sizeof (ProcessTime));
- if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle)) {
+ res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
+ if (!res) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
+ return FALSE;
+ }
+
+ if (!process_handle->child) {
gint64 start_ticks, user_ticks, kernel_ticks;
- mono_process_get_times (GINT_TO_POINTER (WAPI_HANDLE_TO_PID (handle)),
+ mono_process_get_times (GINT_TO_POINTER (process_handle->pid),
&start_ticks, &user_ticks, &kernel_ticks);
ticks_to_processtime (start_ticks, creation_processtime);
return TRUE;
}
- res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
- if (!res) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
- return FALSE;
- }
-
ticks_to_processtime (process_handle->create_time, creation_processtime);
/* A process handle is only signalled if the process has