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

Unified Diff: third_party/psutil/psutil/_psutil_osx.c

Issue 8159001: Update third_party/psutil and fix the licence issue with it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove the suppression and unnecessary files. Created 9 years, 2 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/_psutil_osx.h ('k') | third_party/psutil/psutil/_psutil_posix.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/psutil/psutil/_psutil_osx.c
diff --git a/third_party/psutil/psutil/_psutil_osx.c b/third_party/psutil/psutil/_psutil_osx.c
index 64947a708922ecc306d5a1aeec42bd9d26200517..29162f20b6f757eef9e692a2b8dfa83cc4c3a7a7 100644
--- a/third_party/psutil/psutil/_psutil_osx.c
+++ b/third_party/psutil/psutil/_psutil_osx.c
@@ -1,5 +1,9 @@
/*
- * $Id: _psutil_osx.c 780 2010-11-10 18:42:47Z jloden $
+ * $Id: _psutil_osx.c 1142 2011-10-05 18:45:49Z g.rodola $
+ *
+ * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
*
* OS X platform-specific module methods for _psutil_osx
*/
@@ -10,9 +14,13 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
-#include <signal.h>
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
+#include <libproc.h>
+#include <sys/proc_info.h>
+#include <netinet/tcp_fsm.h>
+#include <arpa/inet.h>
+#include <net/if_dl.h>
#include <mach/mach.h>
#include <mach/task.h>
@@ -22,152 +30,18 @@
#include <mach/mach_traps.h>
#include <mach/shared_memory_server.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOBlockStorageDriver.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/IOBSD.h>
+
#include "_psutil_osx.h"
+#include "_psutil_common.h"
#include "arch/osx/process_info.h"
/*
- * define the psutil C module methods and initialize the module.
- */
-static PyMethodDef
-PsutilMethods[] =
-{
- // --- per-process functions
-
- {"get_process_name", get_process_name, METH_VARARGS,
- "Return process name"},
- {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
- "Return process cmdline as a list of cmdline arguments"},
- {"get_process_ppid", get_process_ppid, METH_VARARGS,
- "Return process ppid as an integer"},
- {"get_process_uid", get_process_uid, METH_VARARGS,
- "Return process real user id as an integer"},
- {"get_process_gid", get_process_gid, METH_VARARGS,
- "Return process real group id as an integer"},
- {"get_cpu_times", get_cpu_times, METH_VARARGS,
- "Return tuple of user/kern time for the given PID"},
- {"get_process_create_time", get_process_create_time, METH_VARARGS,
- "Return a float indicating the process create time expressed in "
- "seconds since the epoch"},
- {"get_memory_info", get_memory_info, METH_VARARGS,
- "Return a tuple of RSS/VMS memory information"},
- {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
- "Return number of threads used by process"},
-
- // --- system-related functions
-
- {"get_pid_list", get_pid_list, METH_VARARGS,
- "Returns a list of PIDs currently running on the system"},
- {"get_num_cpus", get_num_cpus, METH_VARARGS,
- "Return number of CPUs on the system"},
- {"get_total_phymem", get_total_phymem, METH_VARARGS,
- "Return the total amount of physical memory, in bytes"},
- {"get_avail_phymem", get_avail_phymem, METH_VARARGS,
- "Return the amount of available physical memory, in bytes"},
- {"get_total_virtmem", get_total_virtmem, METH_VARARGS,
- "Return the total amount of virtual memory, in bytes"},
- {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS,
- "Return the amount of available virtual memory, in bytes"},
- {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
- "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
-
- {NULL, NULL, 0, NULL}
-};
-
-
-/*
- * Raises an OSError(errno=ESRCH, strerror="No such process") exception
- * in Python.
- */
-static PyObject*
-NoSuchProcess(void) {
- errno = ESRCH;
- return PyErr_SetFromErrno(PyExc_OSError);
-}
-
-/*
- * Raises an OSError(errno=EPERM, strerror="Operation not permitted") exception
- * in Python.
- */
-static PyObject*
-AccessDenied(void) {
- errno = EPERM;
- return PyErr_SetFromErrno(PyExc_OSError);
-}
-
-struct module_state {
- PyObject *error;
-};
-
-#if PY_MAJOR_VERSION >= 3
-#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
-#else
-#define GETSTATE(m) (&_state)
-static struct module_state _state;
-#endif
-
-#if PY_MAJOR_VERSION >= 3
-
-static int
-psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) {
- Py_VISIT(GETSTATE(m)->error);
- return 0;
-}
-
-static int
-psutil_osx_clear(PyObject *m) {
- Py_CLEAR(GETSTATE(m)->error);
- return 0;
-}
-
-
-static struct PyModuleDef
-moduledef = {
- PyModuleDef_HEAD_INIT,
- "psutil_osx",
- NULL,
- sizeof(struct module_state),
- PsutilMethods,
- NULL,
- psutil_osx_traverse,
- psutil_osx_clear,
- NULL
-};
-
-#define INITERROR return NULL
-
-PyObject *
-PyInit__psutil_osx(void)
-
-#else
-#define INITERROR return
-
-void
-init_psutil_osx(void)
-#endif
-{
-#if PY_MAJOR_VERSION >= 3
- PyObject *module = PyModule_Create(&moduledef);
-#else
- PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
-#endif
- if (module == NULL) {
- INITERROR;
- }
- struct module_state *st = GETSTATE(module);
-
- st->error = PyErr_NewException("_psutil_osx.Error", NULL, NULL);
- if (st->error == NULL) {
- Py_DECREF(module);
- INITERROR;
- }
-#if PY_MAJOR_VERSION >= 3
- return module;
-#endif
-}
-
-
-/*
* Return a Python list of all the PIDs running on the system.
*/
static PyObject*
@@ -234,13 +108,7 @@ get_process_cmdline(PyObject* self, PyObject* args)
// get the commandline, defined in arch/osx/process_info.c
arglist = get_arg_list(pid);
-
- // get_arg_list() returns NULL only if getcmdargs failed with ESRCH
- // (no process with that PID)
- if (NULL == arglist) {
- return PyErr_SetFromErrno(PyExc_OSError);
- }
- return Py_BuildValue("N", arglist);
+ return arglist;
}
@@ -266,7 +134,7 @@ get_process_ppid(PyObject* self, PyObject* args)
* Return process real uid from kinfo_proc as a Python integer.
*/
static PyObject*
-get_process_uid(PyObject* self, PyObject* args)
+get_process_uids(PyObject* self, PyObject* args)
{
long pid;
struct kinfo_proc kp;
@@ -276,7 +144,9 @@ get_process_uid(PyObject* self, PyObject* args)
if (get_kinfo_proc(pid, &kp) == -1) {
return NULL;
}
- return Py_BuildValue("l", (long)kp.kp_eproc.e_pcred.p_ruid);
+ return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_ruid,
+ (long)kp.kp_eproc.e_ucred.cr_uid,
+ (long)kp.kp_eproc.e_pcred.p_svuid);
}
@@ -284,7 +154,7 @@ get_process_uid(PyObject* self, PyObject* args)
* Return process real group id from ki_comm as a Python integer.
*/
static PyObject*
-get_process_gid(PyObject* self, PyObject* args)
+get_process_gids(PyObject* self, PyObject* args)
{
long pid;
struct kinfo_proc kp;
@@ -294,30 +164,27 @@ get_process_gid(PyObject* self, PyObject* args)
if (get_kinfo_proc(pid, &kp) == -1) {
return NULL;
}
- return Py_BuildValue("l", (long)kp.kp_eproc.e_pcred.p_rgid);
+ return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_rgid,
+ (long)kp.kp_eproc.e_ucred.cr_groups[0],
+ (long)kp.kp_eproc.e_pcred.p_svgid);
}
/*
- * Return 1 if PID exists in the current process list, else 0.
+ * Return process controlling terminal number as an integer.
*/
-static int
-pid_exists(long pid) {
- int kill_ret;
-
- // save some time if it's an invalid PID
- if (pid < 0) {
- return 0;
+static PyObject*
+get_process_tty_nr(PyObject* self, PyObject* args)
+{
+ long pid;
+ struct kinfo_proc kp;
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
}
-
- // if kill returns success of permission denied we know it's a valid PID
- kill_ret = kill(pid , 0);
- if ( (0 == kill_ret) || (EPERM == errno) ) {
- return 1;
+ if (get_kinfo_proc(pid, &kp) == -1) {
+ return NULL;
}
-
- // otherwise return 0 for PID not found
- return 0;
+ return Py_BuildValue("i", kp.kp_eproc.e_tdev);
}
@@ -356,45 +223,44 @@ get_cpu_times(PyObject* self, PyObject* args)
long pid;
int err;
unsigned int info_count = TASK_BASIC_INFO_COUNT;
- task_port_t task;// = (task_port_t)NULL;
+ task_port_t task; // = (task_port_t)NULL;
time_value_t user_time, system_time;
struct task_basic_info tasks_info;
struct task_thread_times_info task_times;
- // the argument passed should be a process id
if (! PyArg_ParseTuple(args, "l", &pid)) {
return NULL;
}
- /* task_for_pid() requires special privileges
+ /* task_for_pid() requires special privileges
* "This function can be called only if the process is owned by the
* procmod group or if the caller is root."
- * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html
- */
+ * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html */
err = task_for_pid(mach_task_self(), pid, &task);
if ( err == KERN_SUCCESS) {
info_count = TASK_BASIC_INFO_COUNT;
err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
if (err != KERN_SUCCESS) {
- if (err == 4) { // errcode 4 is "invalid argument" (access denied)
+ // errcode 4 is "invalid argument" (access denied)
+ if (err == 4) {
return AccessDenied();
}
- //otherwise throw a runtime error with appropriate error code
- return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
- pid, mach_error_string(err), err);
-
+ // otherwise throw a runtime error with appropriate error code
+ return PyErr_Format(PyExc_RuntimeError,
+ "task_info(TASK_BASIC_INFO) failed");
}
info_count = TASK_THREAD_TIMES_INFO_COUNT;
- err = task_info(task, TASK_THREAD_TIMES_INFO, (task_info_t)&task_times, &info_count);
+ err = task_info(task, TASK_THREAD_TIMES_INFO,
+ (task_info_t)&task_times, &info_count);
if (err != KERN_SUCCESS) {
- if (err == 4) { // errcode 4 is "invalid argument" (access denied)
+ // errcode 4 is "invalid argument" (access denied)
+ if (err == 4) {
return AccessDenied();
}
-
- return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_THREAD_TIMES_INFO) failed for pid %lu - %s (%i)",
- pid, mach_error_string(err), err);
+ return PyErr_Format(PyExc_RuntimeError,
+ "task_info(TASK_BASIC_INFO) failed");
}
}
@@ -402,7 +268,6 @@ get_cpu_times(PyObject* self, PyObject* args)
if (! pid_exists(pid) ) {
return NoSuchProcess();
}
-
// pid exists, so return AccessDenied error since task_for_pid() failed
return AccessDenied();
}
@@ -464,20 +329,19 @@ get_memory_info(PyObject* self, PyObject* args)
/* task_for_pid() requires special privileges
* "This function can be called only if the process is owned by the
* procmod group or if the caller is root."
- * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html
- */
+ * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html */
err = task_for_pid(mach_task_self(), pid, &task);
if ( err == KERN_SUCCESS) {
info_count = TASK_BASIC_INFO_COUNT;
err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
if (err != KERN_SUCCESS) {
- if (err == 4) { // errcode 4 is "invalid argument" (access denied)
+ if (err == 4) {
+ // errcode 4 is "invalid argument" (access denied)
return AccessDenied();
}
-
- //otherwise throw a runtime error with appropriate error code
- return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
- pid, mach_error_string(err), err);
+ // otherwise throw a runtime error with appropriate error code
+ return PyErr_Format(PyExc_RuntimeError,
+ "task_info(TASK_BASIC_INFO) failed");
}
/* Issue #73 http://code.google.com/p/psutil/issues/detail?id=73
@@ -489,8 +353,9 @@ get_memory_info(PyObject* self, PyObject* args)
(vm_region_info_t)&b_info, &info_count, &object_name);
if (err == KERN_SUCCESS) {
if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
- tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE)) {
- tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
+ tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE))
+ {
+ tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
}
}
}
@@ -515,7 +380,7 @@ static PyObject*
get_process_num_threads(PyObject* self, PyObject* args)
{
long pid;
- int err;
+ int err, ret;
unsigned int info_count = TASK_BASIC_INFO_COUNT;
mach_port_t task;
struct task_basic_info tasks_info;
@@ -537,22 +402,28 @@ get_process_num_threads(PyObject* self, PyObject* args)
info_count = TASK_BASIC_INFO_COUNT;
err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
if (err != KERN_SUCCESS) {
- if (err == 4) { // errcode 4 is "invalid argument" (access denied)
+ // errcode 4 is "invalid argument" (access denied)
+ if (err == 4) {
return AccessDenied();
}
- //otherwise throw a runtime error with appropriate error code
- return PyErr_Format(PyExc_RuntimeError, "task_info(TASK_BASIC_INFO) failed for pid %lu - %s (%i)",
- pid, mach_error_string(err), err);
+ // otherwise throw a runtime error with appropriate error code
+ return PyErr_Format(PyExc_RuntimeError,
+ "task_info(TASK_BASIC_INFO) failed");
}
-
err = task_threads(task, &thread_list, &thread_count);
if (err == KERN_SUCCESS) {
+ ret = vm_deallocate(task, (vm_address_t)thread_list,
+ thread_count * sizeof(int));
+ if (ret != KERN_SUCCESS) {
+ printf("vm_deallocate() failed\n");
+ }
return Py_BuildValue("l", (long)thread_count);
}
+ else {
+ return PyErr_Format(PyExc_RuntimeError, "task_thread() failed");
+ }
}
-
-
else {
if (! pid_exists(pid) ) {
return NoSuchProcess();
@@ -584,7 +455,6 @@ get_total_phymem(PyObject* self, PyObject* args)
PyErr_SetFromErrno(0);
return NULL;
}
-
return Py_BuildValue("L", total_phymem);
}
@@ -678,12 +548,883 @@ get_system_cpu_times(PyObject* self, PyObject* args)
"Error in host_statistics(): %s", mach_error_string(error));
}
- //user, nice, system, idle, iowait, irqm, softirq
return Py_BuildValue("(dddd)",
- (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
- (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
- );
+ (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
+ (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
+ );
+}
+
+
+/*
+ * Return a Python list of tuple representing per-cpu times
+ */
+static PyObject*
+get_system_per_cpu_times(PyObject* self, PyObject* args)
+{
+ natural_t cpu_count;
+ processor_info_array_t info_array;
+ mach_msg_type_number_t info_count;
+ kern_return_t error;
+ processor_cpu_load_info_data_t* cpu_load_info;
+ PyObject* py_retlist = PyList_New(0);
+ PyObject* py_cputime;
+ int i, ret;
+
+ error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO,
+ &cpu_count, &info_array, &info_count);
+ if (error != KERN_SUCCESS) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Error in host_processor_info(): %s", mach_error_string(error));
+ }
+
+ cpu_load_info = (processor_cpu_load_info_data_t*) info_array;
+
+ for (i = 0; i < cpu_count; i++) {
+ py_cputime = Py_BuildValue("(dddd)",
+ (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK,
+ (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK,
+ (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK,
+ (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK
+ );
+ PyList_Append(py_retlist, py_cputime);
+ Py_XDECREF(py_cputime);
+ }
+
+ ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
+ info_count * sizeof(int));
+ if (ret != KERN_SUCCESS) {
+ printf("vm_deallocate() failed\n");
+ }
+ return py_retlist;
+}
+
+
+/*
+ * Return a Python float indicating the system boot time expressed in
+ * seconds since the epoch.
+ */
+static PyObject*
+get_system_boot_time(PyObject* self, PyObject* args)
+{
+ /* fetch sysctl "kern.boottime" */
+ static int request[2] = { CTL_KERN, KERN_BOOTTIME };
+ struct timeval result;
+ size_t result_len = sizeof result;
+ time_t boot_time = 0;
+
+ if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) {
+ PyErr_SetFromErrno(0);
+ return NULL;
+ }
+ boot_time = result.tv_sec;
+ return Py_BuildValue("f", (float)boot_time);
+}
+
+
+/*
+ * Return a list of tuples including device, mount point and fs type
+ * for all partitions mounted on the system.
+ */
+static PyObject*
+get_disk_partitions(PyObject* self, PyObject* args)
+{
+ int num;
+ int i;
+ long len;
+ struct statfs *fs;
+ PyObject* py_retlist = PyList_New(0);
+ PyObject* py_tuple;
+
+ // get the number of mount points
+ Py_BEGIN_ALLOW_THREADS
+ num = getfsstat(NULL, 0, MNT_NOWAIT);
+ Py_END_ALLOW_THREADS
+ if (num == -1) {
+ PyErr_SetFromErrno(0);
+ return NULL;
+ }
+
+ len = sizeof(*fs) * num;
+ fs = malloc(len);
+
+ Py_BEGIN_ALLOW_THREADS
+ num = getfsstat(fs, len, MNT_NOWAIT);
+ Py_END_ALLOW_THREADS
+ if (num == -1) {
+ free(fs);
+ PyErr_SetFromErrno(0);
+ return NULL;
+ }
+
+ for (i = 0; i < num; i++) {
+ py_tuple = Py_BuildValue("(sss)", fs[i].f_mntfromname, // device
+ fs[i].f_mntonname, // mount point
+ fs[i].f_fstypename); // fs type
+ PyList_Append(py_retlist, py_tuple);
+ Py_XDECREF(py_tuple);
+ }
+
+ free(fs);
+ return py_retlist;
+}
+
+
+/*
+ * Return process status as a Python integer.
+ */
+static PyObject*
+get_process_status(PyObject* self, PyObject* args)
+{
+ long pid;
+ struct kinfo_proc kp;
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+ if (get_kinfo_proc(pid, &kp) == -1) {
+ return NULL;
+ }
+ return Py_BuildValue("i", (int)kp.kp_proc.p_stat);
}
+
+/*
+ * Return process threads
+ */
+static PyObject*
+get_process_threads(PyObject* self, PyObject* args)
+{
+ long pid;
+ int err, j, ret;
+ kern_return_t kr;
+ unsigned int info_count = TASK_BASIC_INFO_COUNT;
+ mach_port_t task;
+ struct task_basic_info tasks_info;
+ thread_act_port_array_t thread_list;
+ thread_info_data_t thinfo;
+ thread_basic_info_t basic_info_th;
+ mach_msg_type_number_t thread_count, thread_info_count;
+
+ PyObject* retList = PyList_New(0);
+ PyObject* pyTuple = NULL;
+
+ // the argument passed should be a process id
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ // task_for_pid() requires special privileges
+ err = task_for_pid(mach_task_self(), pid, &task);
+ if (err != KERN_SUCCESS) {
+ if (! pid_exists(pid) ) {
+ return NoSuchProcess();
+ }
+ return AccessDenied();
+ }
+
+ info_count = TASK_BASIC_INFO_COUNT;
+ err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
+ if (err != KERN_SUCCESS) {
+ // errcode 4 is "invalid argument" (access denied)
+ if (err == 4) {
+ return AccessDenied();
+ }
+ // otherwise throw a runtime error with appropriate error code
+ return PyErr_Format(PyExc_RuntimeError,
+ "task_info(TASK_BASIC_INFO) failed");
+ }
+
+ err = task_threads(task, &thread_list, &thread_count);
+ if (err != KERN_SUCCESS) {
+ return PyErr_Format(PyExc_RuntimeError, "task_threads() failed");
+ }
+
+ for (j = 0; j < thread_count; j++) {
+ thread_info_count = THREAD_INFO_MAX;
+ kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
+ (thread_info_t)thinfo, &thread_info_count);
+ if (kr != KERN_SUCCESS) {
+ return PyErr_Format(PyExc_RuntimeError, "thread_info() failed");
+ }
+ basic_info_th = (thread_basic_info_t)thinfo;
+ // XXX - thread_info structure does not provide any process id;
+ // the best we can do is assigning an incremental bogus value
+ pyTuple = Py_BuildValue("Iff", j + 1,
+ (float)basic_info_th->user_time.microseconds / 1000000.0,
+ (float)basic_info_th->system_time.microseconds / 1000000.0
+ );
+ PyList_Append(retList, pyTuple);
+ Py_XDECREF(pyTuple);
+ }
+
+ ret = vm_deallocate(task, (vm_address_t)thread_list,
+ thread_count * sizeof(int));
+ if (ret != KERN_SUCCESS) {
+ printf("vm_deallocate() failed\n");
+ }
+
+ return retList;
+}
+
+
+/*
+ * Return process open files as a Python tuple.
+ * References:
+ * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd
+ * - /usr/include/sys/proc_info.h
+ */
+static PyObject*
+get_process_open_files(PyObject* self, PyObject* args)
+{
+ long pid;
+ int pidinfo_result;
+ int iterations;
+ int i;
+ int nb;
+
+ struct proc_fdinfo *fds_pointer;
+ struct proc_fdinfo *fdp_pointer;
+ struct vnode_fdinfowithpath vi;
+
+ PyObject *retList = PyList_New(0);
+ PyObject *tuple = NULL;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
+ if (pidinfo_result <= 0) {
+ goto error;
+ }
+
+ fds_pointer = malloc(pidinfo_result);
+ pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
+ pidinfo_result);
+ free(fds_pointer);
+
+ if (pidinfo_result <= 0) {
+ goto error;
+ }
+
+ iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
+
+ for (i = 0; i < iterations; i++) {
+ fdp_pointer = &fds_pointer[i];
+
+ //
+ if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE)
+ {
+ nb = proc_pidfdinfo(pid,
+ fdp_pointer->proc_fd,
+ PROC_PIDFDVNODEPATHINFO,
+ &vi,
+ sizeof(vi));
+
+ // --- errors checking
+ if (nb <= 0) {
+ if ((errno == ENOENT) || (errno == EBADF)) {
+ // no such file or directory or bad file descriptor;
+ // let's assume the file has been closed or removed
+ continue;
+ }
+ if (errno != 0) {
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+ else
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
+ }
+ if (nb < sizeof(vi)) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
+ }
+ // --- /errors checking
+
+ // --- construct python list
+ tuple = Py_BuildValue("(si)", vi.pvip.vip_path,
+ (int)fdp_pointer->proc_fd);
+ PyList_Append(retList, tuple);
+ Py_DECREF(tuple);
+ // --- /construct python list
+ }
+ }
+
+ return retList;
+
+error:
+ if (errno != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+ else if (! pid_exists(pid) )
+ return NoSuchProcess();
+ else
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDLISTFDS) failed");
+}
+
+
+/*
+ * mathes Linux net/tcp_states.h:
+ * http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
+ */
+static char *
+get_connection_status(int st) {
+ switch (st) {
+ case TCPS_CLOSED:
+ return "CLOSE";
+ case TCPS_CLOSING:
+ return "CLOSING";
+ case TCPS_CLOSE_WAIT:
+ return "CLOSE_WAIT";
+ case TCPS_LISTEN:
+ return "LISTEN";
+ case TCPS_ESTABLISHED:
+ return "ESTABLISHED";
+ case TCPS_SYN_SENT:
+ return "SYN_SENT";
+ case TCPS_SYN_RECEIVED:
+ return "SYN_RECV";
+ case TCPS_FIN_WAIT_1:
+ return "FIN_WAIT_1";
+ case TCPS_FIN_WAIT_2:
+ return "FIN_WAIT_2";
+ case TCPS_LAST_ACK:
+ return "LAST_ACK";
+ case TCPS_TIME_WAIT:
+ return "TIME_WAIT";
+ default:
+ return "";
+ }
+}
+
+
+/*
+ * Return process TCP and UDP connections as a list of tuples.
+ * References:
+ * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0
+ * - /usr/include/sys/proc_info.h
+ */
+static PyObject*
+get_process_connections(PyObject* self, PyObject* args)
+{
+ long pid;
+ int pidinfo_result;
+ int iterations;
+ int i;
+ int nb;
+
+ struct proc_fdinfo *fds_pointer;
+ struct proc_fdinfo *fdp_pointer;
+ struct socket_fdinfo si;
+
+
+ PyObject *retList = PyList_New(0);
+ PyObject *tuple = NULL;
+ PyObject *laddr = NULL;
+ PyObject *raddr = NULL;
+
+ if (! PyArg_ParseTuple(args, "l", &pid)) {
+ return NULL;
+ }
+
+ if (pid == 0) {
+ return retList;
+ }
+
+ pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
+ if (pidinfo_result <= 0) {
+ goto error;
+ }
+
+ fds_pointer = malloc(pidinfo_result);
+ pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
+ pidinfo_result);
+ free(fds_pointer);
+
+ if (pidinfo_result <= 0) {
+ goto error;
+ }
+
+ iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
+
+ for (i = 0; i < iterations; i++) {
+ errno = 0;
+ fdp_pointer = &fds_pointer[i];
+
+ //
+ if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET)
+ {
+ nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, PROC_PIDFDSOCKETINFO,
+ &si, sizeof(si));
+
+ // --- errors checking
+ if (nb <= 0) {
+ if (errno == EBADF) {
+ // let's assume socket has been closed
+ continue;
+ }
+ if (errno != 0) {
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+ else {
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
+ }
+ }
+ if (nb < sizeof(si)) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed (buffer mismatch)");
+ }
+ // --- /errors checking
+
+ //
+ int fd, family, type, lport, rport;
+ char lip[200], rip[200];
+ char *state;
+
+ fd = (int)fdp_pointer->proc_fd;
+ family = si.psi.soi_family;
+ type = si.psi.soi_kind;
+
+ if ((family != AF_INET) && (family != AF_INET6)) {
+ continue;
+ }
+
+ if (type == 2)
+ type = SOCK_STREAM;
+ else if (type == 1)
+ type = SOCK_DGRAM;
+ else
+ continue;
+
+ if (errno != 0) {
+ printf("errno 1 = %i\n", errno);
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+
+
+ if (family == AF_INET) {
+ inet_ntop(AF_INET,
+ &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_46.i46a_addr4,
+ lip,
+ sizeof(lip));
+ inet_ntop(AF_INET,
+ &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_46.i46a_addr4,
+ rip,
+ sizeof(lip));
+ }
+ else {
+ inet_ntop(AF_INET6,
+ &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_laddr.ina_6,
+ lip, sizeof(lip));
+ inet_ntop(AF_INET6,
+ &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr.ina_6,
+ lip, sizeof(rip));
+ }
+
+ // check for inet_ntop failures
+ if (errno != 0) {
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+
+ lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
+ rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
+ if (type == SOCK_STREAM)
+ state = get_connection_status((int)si.psi.soi_proto.pri_tcp.tcpsi_state);
+ else
+ state = "";
+
+ laddr = Py_BuildValue("(si)", lip, lport);
+ if (rport != 0)
+ raddr = Py_BuildValue("(si)", rip, rport);
+ else
+ raddr = PyTuple_New(0);
+
+ // --- construct python list
+ tuple = Py_BuildValue("(iiiNNs)", fd, family, type, laddr, raddr,
+ state);
+ PyList_Append(retList, tuple);
+ Py_DECREF(tuple);
+ // --- /construct python list
+ }
+ }
+
+ return retList;
+
+error:
+ if (errno != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+ else if (! pid_exists(pid) )
+ return NoSuchProcess();
+ else
+ return PyErr_Format(PyExc_RuntimeError,
+ "proc_pidinfo(PROC_PIDLISTFDS) failed");
+}
+
+
+/*
+ * Return a Python list of named tuples with overall network I/O information
+ */
+static PyObject*
+get_network_io_counters(PyObject* self, PyObject* args)
+{
+ PyObject* py_retdict = PyDict_New();
+ PyObject* py_ifc_info;
+
+ char *buf = NULL, *lim, *next;
+ struct if_msghdr *ifm;
+ int mib[6];
+ size_t len;
+
+ mib[0] = CTL_NET; // networking subsystem
+ mib[1] = PF_ROUTE; // type of information
+ mib[2] = 0; // protocol (IPPROTO_xxx)
+ mib[3] = 0; // address family
+ mib[4] = NET_RT_IFLIST2; // operation
+ mib[5] = 0;
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
+ Py_DECREF(py_retdict);
+ PyErr_SetFromErrno(0);
+ return NULL;
+ }
+
+ buf = malloc(len);
+
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
+ if (buf) {
+ free(buf);
+ }
+ Py_DECREF(py_retdict);
+ PyErr_SetFromErrno(0);
+ return NULL;
+ }
+
+ lim = buf + len;
+
+ for (next = buf; next < lim; ) {
+ ifm = (struct if_msghdr *)next;
+ next += ifm->ifm_msglen;
+
+ if (ifm->ifm_type == RTM_IFINFO2) {
+ struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1);
+ char ifc_name[32];
+
+ strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen);
+ ifc_name[sdl->sdl_nlen] = 0;
+
+ py_ifc_info = Py_BuildValue("(KKKK)",
+ if2m->ifm_data.ifi_obytes,
+ if2m->ifm_data.ifi_ibytes,
+ if2m->ifm_data.ifi_opackets,
+ if2m->ifm_data.ifi_ipackets);
+ PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info);
+ Py_XDECREF(py_ifc_info);
+ }
+ else {
+ continue;
+ }
+ }
+
+ free(buf);
+
+ return py_retdict;
+}
+
+
+/*
+ * Return a Python dict of tuples for disk I/O information
+ */
+static PyObject*
+get_disk_io_counters(PyObject* self, PyObject* args)
+{
+ PyObject* py_retdict = PyDict_New();
+ PyObject* py_disk_info;
+
+ CFDictionaryRef parent_dict;
+ CFDictionaryRef props_dict;
+ CFDictionaryRef stats_dict;
+ io_registry_entry_t parent;
+ io_registry_entry_t disk;
+ io_iterator_t disk_list;
+
+ /* Get list of disks */
+ if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+ IOServiceMatching(kIOMediaClass),
+ &disk_list) != kIOReturnSuccess) {
+ Py_DECREF(py_retdict);
+ PyErr_SetString(PyExc_RuntimeError, "Unable to get the list of disks.");
+ return NULL;
+ }
+
+ /* Iterate over disks */
+ while ((disk = IOIteratorNext(disk_list)) != 0) {
+ parent_dict = NULL;
+ props_dict = NULL;
+ stats_dict = NULL;
+
+ if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) != kIOReturnSuccess) {
+ PyErr_SetString(PyExc_RuntimeError, "Unable to get the disk's parent.");
+ Py_DECREF(py_retdict);
+ IOObjectRelease(disk);
+ return NULL;
+ }
+
+ if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
+ if(IORegistryEntryCreateCFProperties(
+ disk,
+ (CFMutableDictionaryRef *) &parent_dict,
+ kCFAllocatorDefault,
+ kNilOptions) != kIOReturnSuccess)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Unable to get the parent's properties.");
+ Py_DECREF(py_retdict);
+ IOObjectRelease(disk);
+ IOObjectRelease(parent);
+ return NULL;
+ }
+
+ if (IORegistryEntryCreateCFProperties(parent,
+ (CFMutableDictionaryRef *) &props_dict,
+ kCFAllocatorDefault,
+ kNilOptions) != kIOReturnSuccess)
+ {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Unable to get the disk properties.");
+ Py_DECREF(py_retdict);
+ IOObjectRelease(disk);
+ return NULL;
+ }
+
+ const int kMaxDiskNameSize = 64;
+ CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue(
+ parent_dict,
+ CFSTR(kIOBSDNameKey));
+ char disk_name[kMaxDiskNameSize];
+
+ CFStringGetCString(disk_name_ref,
+ disk_name,
+ kMaxDiskNameSize,
+ CFStringGetSystemEncoding());
+
+ stats_dict = (CFDictionaryRef)CFDictionaryGetValue(
+ props_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsKey));
+
+ if (stats_dict == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Unable to get disk stats.");
+ Py_DECREF(py_retdict);
+ CFRelease(props_dict);
+ IOObjectRelease(disk);
+ IOObjectRelease(parent);
+ return NULL;
+ }
+
+ CFNumberRef number;
+ int64_t reads, writes, read_bytes, write_bytes, read_time, write_time = 0;
+
+ /* Get disk reads/writes */
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsReadsKey))))
+ {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &reads);
+ }
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsWritesKey))))
+ {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &writes);
+ }
+
+ /* Get disk bytes read/written */
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey))))
+ {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes);
+ }
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey))))
+ {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes);
+ }
+
+ /* Get disk time spent reading/writing (nanoseconds) */
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey))))
+ {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &read_time);
+ }
+ if ((number = (CFNumberRef)CFDictionaryGetValue(
+ stats_dict,
+ CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &write_time);
+ }
+
+ py_disk_info = Py_BuildValue("(KKKKKK)",
+ reads, writes,
+ read_bytes, write_bytes,
+ read_time, write_time);
+ PyDict_SetItemString(py_retdict, disk_name, py_disk_info);
+ Py_XDECREF(py_disk_info);
+
+ CFRelease(parent_dict);
+ IOObjectRelease(parent);
+ CFRelease(props_dict);
+ IOObjectRelease(disk);
+ }
+ }
+
+ IOObjectRelease (disk_list);
+
+ return py_retdict;
+}
+
+
+/*
+ * define the psutil C module methods and initialize the module.
+ */
+static PyMethodDef
+PsutilMethods[] =
+{
+ // --- per-process functions
+
+ {"get_process_name", get_process_name, METH_VARARGS,
+ "Return process name"},
+ {"get_process_cmdline", get_process_cmdline, METH_VARARGS,
+ "Return process cmdline as a list of cmdline arguments"},
+ {"get_process_ppid", get_process_ppid, METH_VARARGS,
+ "Return process ppid as an integer"},
+ {"get_process_uids", get_process_uids, METH_VARARGS,
+ "Return process real user id as an integer"},
+ {"get_process_gids", get_process_gids, METH_VARARGS,
+ "Return process real group id as an integer"},
+ {"get_cpu_times", get_cpu_times, METH_VARARGS,
+ "Return tuple of user/kern time for the given PID"},
+ {"get_process_create_time", get_process_create_time, METH_VARARGS,
+ "Return a float indicating the process create time expressed in "
+ "seconds since the epoch"},
+ {"get_memory_info", get_memory_info, METH_VARARGS,
+ "Return a tuple of RSS/VMS memory information"},
+ {"get_process_num_threads", get_process_num_threads, METH_VARARGS,
+ "Return number of threads used by process"},
+ {"get_process_status", get_process_status, METH_VARARGS,
+ "Return process status as an integer"},
+ {"get_process_threads", get_process_threads, METH_VARARGS,
+ "Return process threads as a list of tuples"},
+ {"get_process_open_files", get_process_open_files, METH_VARARGS,
+ "Return files opened by process as a list of tuples"},
+ {"get_process_connections", get_process_connections, METH_VARARGS,
+ "Get process TCP and UDP connections as a list of tuples"},
+ {"get_process_tty_nr", get_process_tty_nr, METH_VARARGS,
+ "Return process tty number as an integer"},
+
+ // --- system-related functions
+
+ {"get_pid_list", get_pid_list, METH_VARARGS,
+ "Returns a list of PIDs currently running on the system"},
+ {"get_num_cpus", get_num_cpus, METH_VARARGS,
+ "Return number of CPUs on the system"},
+ {"get_total_phymem", get_total_phymem, METH_VARARGS,
+ "Return the total amount of physical memory, in bytes"},
+ {"get_avail_phymem", get_avail_phymem, METH_VARARGS,
+ "Return the amount of available physical memory, in bytes"},
+ {"get_total_virtmem", get_total_virtmem, METH_VARARGS,
+ "Return the total amount of virtual memory, in bytes"},
+ {"get_avail_virtmem", get_avail_virtmem, METH_VARARGS,
+ "Return the amount of available virtual memory, in bytes"},
+ {"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
+ "Return system cpu times as a tuple (user, system, nice, idle, irc)"},
+ {"get_system_per_cpu_times", get_system_per_cpu_times, METH_VARARGS,
+ "Return system per-cpu times as a list of tuples"},
+ {"get_system_boot_time", get_system_boot_time, METH_VARARGS,
+ "Return a float indicating the system boot time expressed in "
+ "seconds since the epoch"},
+ {"get_disk_partitions", get_disk_partitions, METH_VARARGS,
+ "Return a list of tuples including device, mount point and "
+ "fs type for all partitions mounted on the system."},
+ {"get_network_io_counters", get_network_io_counters, METH_VARARGS,
+ "Return dict of tuples of networks I/O information."},
+ {"get_disk_io_counters", get_disk_io_counters, METH_VARARGS,
+ "Return dict of tuples of disks I/O information."},
+
+ {NULL, NULL, 0, NULL}
+};
+
+
+struct module_state {
+ PyObject *error;
+};
+
+#if PY_MAJOR_VERSION >= 3
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+#else
+#define GETSTATE(m) (&_state)
+#endif
+
+#if PY_MAJOR_VERSION >= 3
+
+static int
+psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) {
+ Py_VISIT(GETSTATE(m)->error);
+ return 0;
+}
+
+static int
+psutil_osx_clear(PyObject *m) {
+ Py_CLEAR(GETSTATE(m)->error);
+ return 0;
+}
+
+
+static struct PyModuleDef
+moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "psutil_osx",
+ NULL,
+ sizeof(struct module_state),
+ PsutilMethods,
+ NULL,
+ psutil_osx_traverse,
+ psutil_osx_clear,
+ NULL
+};
+
+#define INITERROR return NULL
+
+PyObject *
+PyInit__psutil_osx(void)
+
+#else
+#define INITERROR return
+
+void
+init_psutil_osx(void)
+#endif
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *module = PyModule_Create(&moduledef);
+#else
+ PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
+#endif
+ // process status constants, defined in:
+ // http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149
+ PyModule_AddIntConstant(module, "SIDL", SIDL);
+ PyModule_AddIntConstant(module, "SRUN", SRUN);
+ PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
+ PyModule_AddIntConstant(module, "SSTOP", SSTOP);
+ PyModule_AddIntConstant(module, "SZOMB", SZOMB);
+
+ if (module == NULL) {
+ INITERROR;
+ }
+#if PY_MAJOR_VERSION >= 3
+ return module;
+#endif
+}
« no previous file with comments | « third_party/psutil/psutil/_psutil_osx.h ('k') | third_party/psutil/psutil/_psutil_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698