Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Unified Diff: third_party/psutil/psutil/arch/osx/process_info.c

Issue 6246123: Moving psutil to third_party. This is first step for Media Performance test project. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: modification based on code review's comments Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/psutil/psutil/arch/osx/process_info.h ('k') | third_party/psutil/psutil/compat.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/psutil/psutil/arch/osx/process_info.c
diff --git a/third_party/psutil/psutil/arch/osx/process_info.c b/third_party/psutil/psutil/arch/osx/process_info.c
new file mode 100644
index 0000000000000000000000000000000000000000..53b04098f67066104d784969d88af7cbd3a0d607
--- /dev/null
+++ b/third_party/psutil/psutil/arch/osx/process_info.c
@@ -0,0 +1,301 @@
+/*
+ * $Id: process_info.c 772 2010-11-03 13:51:11Z g.rodola $
+ *
+ * Helper functions related to fetching process information. Used by _psutil_osx
+ * module methods.
+ */
+
+#include <Python.h>
+#include <assert.h>
+#include <errno.h>
+#include <limits.h> /* for INT_MAX */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/sysctl.h>
+
+#include "process_info.h"
+
+#define ARGS_ACCESS_DENIED -2
+
+
+
+/*
+ * Returns a list of all BSD processes on the system. This routine
+ * allocates the list and puts it in *procList and a count of the
+ * number of entries in *procCount. You are responsible for freeing
+ * this list (use "free" from System framework).
+ * On success, the function returns 0.
+ * On error, the function returns a BSD errno value.
+ */
+int
+get_proc_list(kinfo_proc **procList, size_t *procCount)
+{
+ /* Declaring mib as const requires use of a cast since the
+ * sysctl prototype doesn't include the const modifier. */
+ static const int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
+ size_t size, size2;
+ void *ptr;
+ int err, lim = 8; /* some limit */
+
+ assert( procList != NULL);
+ assert(*procList == NULL);
+ assert(procCount != NULL);
+
+ *procCount = 0;
+
+ /* We start by calling sysctl with ptr == NULL and size == 0.
+ * That will succeed, and set size to the appropriate length.
+ * We then allocate a buffer of at least that size and call
+ * sysctl with that buffer. If that succeeds, we're done.
+ * If that call fails with ENOMEM, we throw the buffer away
+ * and try again.
+ * Note that the loop calls sysctl with NULL again. This is
+ * is necessary because the ENOMEM failure case sets size to
+ * the amount of data returned, not the amount of data that
+ * could have been returned.
+ */
+ while (lim-- > 0) {
+ size = 0;
+ if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) {
+ return errno;
+ }
+
+ size2 = size + (size >> 3); /* add some */
+ if (size2 > size) {
+ ptr = malloc(size2);
+ if (ptr == NULL) {
+ ptr = malloc(size);
+ } else {
+ size = size2;
+ }
+ }
+ else {
+ ptr = malloc(size);
+ }
+ if (ptr == NULL) {
+ return ENOMEM;
+ }
+
+ if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) {
+ err = errno;
+ free(ptr);
+ if (err != ENOMEM) {
+ return err;
+ }
+
+ } else {
+ *procList = (kinfo_proc *)ptr;
+ *procCount = size / sizeof(kinfo_proc);
+ return 0;
+ }
+ }
+ return ENOMEM;
+}
+
+
+/*
+ * Modified from psi Python System Information project
+ *
+ * Get command path, arguments and environment variables.
+ *
+ * Based on code from ps.
+ *
+ * Returns:
+ * 0 for success
+ * 1 for sysctl error, errno exception raised
+ * -1 for failure, system or memory exception raised
+ * -2 rather ARGS_ACCESS_DENIED, for insufficient privileges
+ */
+int
+getcmdargs(long pid, PyObject **exec_path, PyObject **envlist, PyObject **arglist)
+{
+ int nargs, mib[3];
+ size_t size, argmax;
+ char *curr_arg, *start_args, *iter_args, *end_args;
+ char *procargs = NULL;
+ char *err = NULL;
+ PyObject *arg;
+
+ *arglist = Py_BuildValue("[]"); /* empty list */
+ if (*arglist == NULL) {
+ err = "getcmdargs(): arglist exception";
+ goto ERROR_RETURN;
+ }
+
+ /* Get the maximum process arguments size. */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+
+ size = sizeof(argmax);
+ if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
+ PyErr_SetFromErrno(NULL);
+ return errno;
+ }
+
+ /* Allocate space for the arguments. */
+ procargs = (char *)malloc(argmax);
+ if (procargs == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "getcmdargs(): insufficient memory for procargs");
+ return ENOMEM;
+ }
+
+ /*
+ * Make a sysctl() call to get the raw argument space of the process.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCARGS2;
+ mib[2] = (int)pid;
+
+ size = argmax;
+ if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
+ if (EINVAL == errno) { // invalid == access denied for some reason
+ free(procargs);
+ return ARGS_ACCESS_DENIED; /* Insufficient privileges */
+ }
+
+ PyErr_SetFromErrno(PyExc_OSError);
+ free(procargs);
+ return errno;
+ }
+
+ // copy the number of argument to nargs
+ memcpy(&nargs, procargs, sizeof(nargs));
+ iter_args = procargs + sizeof(nargs);
+ end_args = &procargs[size]; // end of the argument space
+ if (iter_args >= end_args) {
+ err = "getcmdargs(): argument length mismatch";
+ goto ERROR_RETURN;
+ }
+
+ // Save the path
+ if (NULL != exec_path) {
+ *exec_path = Py_BuildValue("s", iter_args);
+ if (*exec_path == NULL) {
+ err = "getcmdargs(): exec_path exception";
+ goto ERROR_RETURN;
+ }
+ }
+
+ //TODO: save the environment variables to envlist as well
+ // Skip over the exec_path and '\0' characters.
+ while (iter_args < end_args && *iter_args != '\0') { iter_args++; }
+ while (iter_args < end_args && *iter_args == '\0') { iter_args++; }
+
+ /* Iterate through the '\0'-terminated strings and add each string
+ * to the Python List arglist as a Python string.
+ * Stop when nargs strings have been extracted. That should be all
+ * the arguments. The rest of the strings will be environment
+ * strings for the command.
+ */
+ curr_arg = iter_args;
+ start_args = iter_args; //reset start position to beginning of cmdline
+ while (iter_args < end_args && nargs > 0) {
+ if (*iter_args++ == '\0') {
+ /* Fetch next argument */
+ arg = Py_BuildValue("s", curr_arg);
+ if (arg == NULL) {
+ err = "getcmdargs(): exception building argument string";
+ goto ERROR_RETURN;
+ }
+ PyList_Append(*arglist, arg);
+ Py_DECREF(arg);
+
+ curr_arg = iter_args;
+ nargs--;
+ }
+ }
+
+ /*
+ * curr_arg position should be further than the start of the argspace
+ * and number of arguments should be 0 after iterating above. Otherwise
+ * we had an empty argument space or a missing terminating \0 etc.
+ */
+ if (curr_arg == start_args || nargs > 0) {
+ err = "getcmdargs(): argument parsing failed";
+ goto ERROR_RETURN;
+ }
+
+ERROR_RETURN:
+ // Clean up.
+ if (NULL != procargs) {
+ free(procargs);
+ }
+ if (NULL != err) {
+ PyErr_SetString(PyExc_SystemError, err);
+ return -1;
+ }
+ return 0;
+}
+
+
+/* return process args as a python list */
+PyObject*
+get_arg_list(long pid)
+{
+ int r;
+ PyObject *argList;
+ PyObject *env = NULL;
+ PyObject *args = NULL;
+ PyObject *exec_path = NULL;
+
+ //special case for PID 0 (kernel_task) where cmdline cannot be fetched
+ if (pid == 0) {
+ return Py_BuildValue("[]");
+ }
+
+ /* Fetch the command-line arguments and environment variables */
+ //printf("pid: %ld\n", pid);
+ if (pid < 0 || pid > (long)INT_MAX) {
+ return Py_BuildValue("");
+ }
+
+ r = getcmdargs(pid, &exec_path, &env, &args);
+ if (r == 0) {
+ //PySequence_Tuple(args);
+ argList = PySequence_List(args);
+ }
+ else if (r == ARGS_ACCESS_DENIED) { //-2
+ argList = Py_BuildValue("[]");
+ }
+ else {
+ argList = Py_BuildValue("");
+ }
+
+ Py_XDECREF(args);
+ Py_XDECREF(exec_path);
+ Py_XDECREF(env);
+ return argList;
+}
+
+
+int
+get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
+{
+ int mib[4];
+ size_t len;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+
+ // fetch the info with sysctl()
+ len = sizeof(struct kinfo_proc);
+
+ // now read the data from sysctl
+ if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) {
+ // raise an exception and throw errno as the error
+ PyErr_SetFromErrno(PyExc_OSError);
+ }
+
+ /*
+ * sysctl succeeds but len is zero, happens when process has gone away
+ */
+ if (len == 0) {
+ errno = ESRCH;
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ return 0;
+}
« no previous file with comments | « third_party/psutil/psutil/arch/osx/process_info.h ('k') | third_party/psutil/psutil/compat.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698