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

Side by Side Diff: third_party/psutil/psutil/arch/osx/process_info.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 unified diff | Download patch | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * $Id: process_info.c 772 2010-11-03 13:51:11Z g.rodola $ 2 * $Id: process_info.c 1142 2011-10-05 18:45:49Z g.rodola $
3 *
4 * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
3 * 7 *
4 * Helper functions related to fetching process information. Used by _psutil_osx 8 * Helper functions related to fetching process information. Used by _psutil_osx
5 * module methods. 9 * module methods.
6 */ 10 */
7 11
8 #include <Python.h> 12 #include <Python.h>
9 #include <assert.h> 13 #include <assert.h>
10 #include <errno.h> 14 #include <errno.h>
11 #include <limits.h> /* for INT_MAX */ 15 #include <limits.h> /* for INT_MAX */
12 #include <stdbool.h> 16 #include <stdbool.h>
13 #include <stdlib.h> 17 #include <stdlib.h>
14 #include <stdio.h> 18 #include <stdio.h>
19 #include <signal.h>
15 #include <sys/sysctl.h> 20 #include <sys/sysctl.h>
16 21
17 #include "process_info.h" 22 #include "process_info.h"
23 #include "../../_psutil_common.h"
18 24
19 #define ARGS_ACCESS_DENIED -2 25
26 /*
27 * Return 1 if PID exists in the current process list, else 0.
28 */
29 int
30 pid_exists(long pid)
31 {
32 int kill_ret;
33
34 // save some time if it's an invalid PID
35 if (pid < 0) {
36 return 0;
37 }
38
39 // if kill returns success of permission denied we know it's a valid PID
40 kill_ret = kill(pid , 0);
41 if ( (0 == kill_ret) || (EPERM == errno) ) {
42 return 1;
43 }
44
45 // otherwise return 0 for PID not found
46 return 0;
47 }
20 48
21 49
22 50
23 /* 51 /*
24 * Returns a list of all BSD processes on the system. This routine 52 * Returns a list of all BSD processes on the system. This routine
25 * allocates the list and puts it in *procList and a count of the 53 * allocates the list and puts it in *procList and a count of the
26 * number of entries in *procCount. You are responsible for freeing 54 * number of entries in *procCount. You are responsible for freeing
27 * this list (use "free" from System framework). 55 * this list (use "free" from System framework).
28 * On success, the function returns 0. 56 * On success, the function returns 0.
29 * On error, the function returns a BSD errno value. 57 * On error, the function returns a BSD errno value.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } else { 115 } else {
88 *procList = (kinfo_proc *)ptr; 116 *procList = (kinfo_proc *)ptr;
89 *procCount = size / sizeof(kinfo_proc); 117 *procCount = size / sizeof(kinfo_proc);
90 return 0; 118 return 0;
91 } 119 }
92 } 120 }
93 return ENOMEM; 121 return ENOMEM;
94 } 122 }
95 123
96 124
97 /* 125 /* Read the maximum argument size for processes */
98 * Modified from psi Python System Information project
99 *
100 * Get command path, arguments and environment variables.
101 *
102 * Based on code from ps.
103 *
104 * Returns:
105 * 0 for success
106 * 1 for sysctl error, errno exception raised
107 * -1 for failure, system or memory exception raised
108 * -2 rather ARGS_ACCESS_DENIED, for insufficient privileges
109 */
110 int 126 int
111 getcmdargs(long pid, PyObject **exec_path, PyObject **envlist, PyObject **arglis t) 127 get_argmax()
112 { 128 {
113 int nargs, mib[3]; 129 int argmax;
114 size_t size, argmax; 130 int mib[] = { CTL_KERN, KERN_ARGMAX };
115 char *curr_arg, *start_args, *iter_args, *end_args; 131 size_t size = sizeof(argmax);
116 char *procargs = NULL;
117 char *err = NULL;
118 PyObject *arg;
119 132
120 *arglist = Py_BuildValue("[]"); /* empty list */ 133 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) {
121 if (*arglist == NULL) { 134 return argmax;
122 err = "getcmdargs(): arglist exception";
123 goto ERROR_RETURN;
124 }
125
126 /* Get the maximum process arguments size. */
127 mib[0] = CTL_KERN;
128 mib[1] = KERN_ARGMAX;
129
130 size = sizeof(argmax);
131 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
132 PyErr_SetFromErrno(NULL);
133 return errno;
134 }
135
136 /* Allocate space for the arguments. */
137 procargs = (char *)malloc(argmax);
138 if (procargs == NULL) {
139 PyErr_SetString(PyExc_MemoryError,
140 "getcmdargs(): insufficient memory for procargs");
141 return ENOMEM;
142 }
143
144 /*
145 * Make a sysctl() call to get the raw argument space of the process.
146 */
147 mib[0] = CTL_KERN;
148 mib[1] = KERN_PROCARGS2;
149 mib[2] = (int)pid;
150
151 size = argmax;
152 if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
153 if (EINVAL == errno) { // invalid == access denied for some reason
154 free(procargs);
155 return ARGS_ACCESS_DENIED; /* Insufficient privileges */
156 }
157
158 PyErr_SetFromErrno(PyExc_OSError);
159 free(procargs);
160 return errno;
161 }
162
163 // copy the number of argument to nargs
164 memcpy(&nargs, procargs, sizeof(nargs));
165 iter_args = procargs + sizeof(nargs);
166 end_args = &procargs[size]; // end of the argument space
167 if (iter_args >= end_args) {
168 err = "getcmdargs(): argument length mismatch";
169 goto ERROR_RETURN;
170 }
171
172 // Save the path
173 if (NULL != exec_path) {
174 *exec_path = Py_BuildValue("s", iter_args);
175 if (*exec_path == NULL) {
176 err = "getcmdargs(): exec_path exception";
177 goto ERROR_RETURN;
178 }
179 }
180
181 //TODO: save the environment variables to envlist as well
182 // Skip over the exec_path and '\0' characters.
183 while (iter_args < end_args && *iter_args != '\0') { iter_args++; }
184 while (iter_args < end_args && *iter_args == '\0') { iter_args++; }
185
186 /* Iterate through the '\0'-terminated strings and add each string
187 * to the Python List arglist as a Python string.
188 * Stop when nargs strings have been extracted. That should be all
189 * the arguments. The rest of the strings will be environment
190 * strings for the command.
191 */
192 curr_arg = iter_args;
193 start_args = iter_args; //reset start position to beginning of cmdline
194 while (iter_args < end_args && nargs > 0) {
195 if (*iter_args++ == '\0') {
196 /* Fetch next argument */
197 arg = Py_BuildValue("s", curr_arg);
198 if (arg == NULL) {
199 err = "getcmdargs(): exception building argument string";
200 goto ERROR_RETURN;
201 }
202 PyList_Append(*arglist, arg);
203 Py_DECREF(arg);
204
205 curr_arg = iter_args;
206 nargs--;
207 }
208 }
209
210 /*
211 * curr_arg position should be further than the start of the argspace
212 * and number of arguments should be 0 after iterating above. Otherwise
213 * we had an empty argument space or a missing terminating \0 etc.
214 */
215 if (curr_arg == start_args || nargs > 0) {
216 err = "getcmdargs(): argument parsing failed";
217 goto ERROR_RETURN;
218 }
219
220 ERROR_RETURN:
221 // Clean up.
222 if (NULL != procargs) {
223 free(procargs);
224 }
225 if (NULL != err) {
226 PyErr_SetString(PyExc_SystemError, err);
227 return -1;
228 } 135 }
229 return 0; 136 return 0;
230 } 137 }
231 138
232 139
233 /* return process args as a python list */ 140 /* return process args as a python list */
234 PyObject* 141 PyObject*
235 get_arg_list(long pid) 142 get_arg_list(long pid)
236 { 143 {
237 int r; 144 int mib[3];
238 PyObject *argList; 145 int nargs;
239 PyObject *env = NULL; 146 int len;
240 PyObject *args = NULL; 147 char *procargs;
241 PyObject *exec_path = NULL; 148 char *arg_ptr;
149 char *arg_end;
150 char *curr_arg;
151 size_t argmax;
152 PyObject *arg = NULL;
153 PyObject *arglist = NULL;
242 154
243 //special case for PID 0 (kernel_task) where cmdline cannot be fetched 155 //special case for PID 0 (kernel_task) where cmdline cannot be fetched
244 if (pid == 0) { 156 if (pid == 0) {
245 return Py_BuildValue("[]"); 157 return Py_BuildValue("[]");
246 } 158 }
247 159
248 /* Fetch the command-line arguments and environment variables */ 160 /* read argmax and allocate memory for argument space. */
249 //printf("pid: %ld\n", pid); 161 argmax = get_argmax();
250 if (pid < 0 || pid > (long)INT_MAX) { 162 if (! argmax) { return PyErr_SetFromErrno(PyExc_OSError); }
251 return Py_BuildValue(""); 163
164 procargs = (char *)malloc(argmax);
165 if (NULL == procargs) {
166 return PyErr_SetFromErrno(PyExc_OSError);
252 } 167 }
253 168
254 r = getcmdargs(pid, &exec_path, &env, &args); 169 /* read argument space */
255 if (r == 0) { 170 mib[0] = CTL_KERN;
256 //PySequence_Tuple(args); 171 mib[1] = KERN_PROCARGS2;
257 argList = PySequence_List(args); 172 mib[2] = pid;
258 } 173 if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
259 else if (r == ARGS_ACCESS_DENIED) { //-2 174 if (EINVAL == errno) { // invalid == access denied OR nonexistent PID
260 argList = Py_BuildValue("[]"); 175 if ( pid_exists(pid) ) {
261 } 176 AccessDenied();
262 else { 177 } else {
263 argList = Py_BuildValue(""); 178 NoSuchProcess();
179 }
180 }
181 free(procargs);
182 return NULL;
264 } 183 }
265 184
266 Py_XDECREF(args); 185 arg_end = &procargs[argmax];
267 Py_XDECREF(exec_path); 186 /* copy the number of arguments to nargs */
268 Py_XDECREF(env); 187 memcpy(&nargs, procargs, sizeof(nargs));
269 return argList; 188
189 arg_ptr = procargs + sizeof(nargs);
190 len = strlen(arg_ptr);
191 arg_ptr += len + 1;
192
193 if (arg_ptr == arg_end) {
194 free(procargs);
195 return Py_BuildValue("[]");
196 }
197
198 // skip ahead to the first argument
199 for (; arg_ptr < arg_end; arg_ptr++) {
200 if (*arg_ptr != '\0') {
201 break;
202 }
203 }
204
205 /* iterate through arguments */
206 curr_arg = arg_ptr;
207 arglist = Py_BuildValue("[]");
208 while (arg_ptr < arg_end && nargs > 0) {
209 if (*arg_ptr++ == '\0') {
210 arg = Py_BuildValue("s", curr_arg);
211 if (NULL == arg) {
212 return NULL;
213 }
214 PyList_Append(arglist, arg);
215 Py_DECREF(arg);
216 // iterate to next arg and decrement # of args
217 curr_arg = arg_ptr;
218 nargs--;
219 }
220 }
221
222 free(procargs);
223 return arglist;
270 } 224 }
271 225
272 226
273 int 227 int
274 get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) 228 get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
275 { 229 {
276 int mib[4]; 230 int mib[4];
277 size_t len; 231 size_t len;
278 mib[0] = CTL_KERN; 232 mib[0] = CTL_KERN;
279 mib[1] = KERN_PROC; 233 mib[1] = KERN_PROC;
280 mib[2] = KERN_PROC_PID; 234 mib[2] = KERN_PROC_PID;
281 mib[3] = pid; 235 mib[3] = pid;
282 236
283 // fetch the info with sysctl() 237 // fetch the info with sysctl()
284 len = sizeof(struct kinfo_proc); 238 len = sizeof(struct kinfo_proc);
285 239
286 // now read the data from sysctl 240 // now read the data from sysctl
287 if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) { 241 if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) {
288 // raise an exception and throw errno as the error 242 // raise an exception and throw errno as the error
289 PyErr_SetFromErrno(PyExc_OSError); 243 PyErr_SetFromErrno(PyExc_OSError);
290 } 244 }
291 245
292 /* 246 /*
293 * sysctl succeeds but len is zero, happens when process has gone away 247 * sysctl succeeds but len is zero, happens when process has gone away
294 */ 248 */
295 if (len == 0) { 249 if (len == 0) {
296 errno = ESRCH; 250 NoSuchProcess();
297 PyErr_SetFromErrno(PyExc_OSError);
298 return -1; 251 return -1;
299 } 252 }
300 return 0; 253 return 0;
301 } 254 }
OLDNEW
« 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