Line data Source code
1 :
2 : #include "Python.h"
3 : #include <sys/resource.h>
4 : #include <sys/time.h>
5 : #include <string.h>
6 : #include <errno.h>
7 : /* for sysconf */
8 : #if defined(HAVE_UNISTD_H)
9 : #include <unistd.h>
10 : #endif
11 :
12 : /* On some systems, these aren't in any header file.
13 : On others they are, with inconsistent prototypes.
14 : We declare the (default) return type, to shut up gcc -Wall;
15 : but we can't declare the prototype, to avoid errors
16 : when the header files declare it different.
17 : Worse, on some Linuxes, getpagesize() returns a size_t... */
18 :
19 : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
20 :
21 : PyDoc_STRVAR(struct_rusage__doc__,
22 : "struct_rusage: Result from getrusage.\n\n"
23 : "This object may be accessed either as a tuple of\n"
24 : " (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n"
25 : " nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n"
26 : "or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.");
27 :
28 : static PyStructSequence_Field struct_rusage_fields[] = {
29 : {"ru_utime", "user time used"},
30 : {"ru_stime", "system time used"},
31 : {"ru_maxrss", "max. resident set size"},
32 : {"ru_ixrss", "shared memory size"},
33 : {"ru_idrss", "unshared data size"},
34 : {"ru_isrss", "unshared stack size"},
35 : {"ru_minflt", "page faults not requiring I/O"},
36 : {"ru_majflt", "page faults requiring I/O"},
37 : {"ru_nswap", "number of swap outs"},
38 : {"ru_inblock", "block input operations"},
39 : {"ru_oublock", "block output operations"},
40 : {"ru_msgsnd", "IPC messages sent"},
41 : {"ru_msgrcv", "IPC messages received"},
42 : {"ru_nsignals", "signals received"},
43 : {"ru_nvcsw", "voluntary context switches"},
44 : {"ru_nivcsw", "involuntary context switches"},
45 : {0}
46 : };
47 :
48 : static PyStructSequence_Desc struct_rusage_desc = {
49 : "resource.struct_rusage", /* name */
50 : struct_rusage__doc__, /* doc */
51 : struct_rusage_fields, /* fields */
52 : 16 /* n_in_sequence */
53 : };
54 :
55 : static int initialized;
56 : static PyTypeObject StructRUsageType;
57 :
58 : static PyObject *
59 0 : resource_getrusage(PyObject *self, PyObject *args)
60 : {
61 : int who;
62 : struct rusage ru;
63 : PyObject *result;
64 :
65 0 : if (!PyArg_ParseTuple(args, "i:getrusage", &who))
66 0 : return NULL;
67 :
68 0 : if (getrusage(who, &ru) == -1) {
69 0 : if (errno == EINVAL) {
70 0 : PyErr_SetString(PyExc_ValueError,
71 : "invalid who parameter");
72 0 : return NULL;
73 : }
74 0 : PyErr_SetFromErrno(PyExc_OSError);
75 0 : return NULL;
76 : }
77 :
78 0 : result = PyStructSequence_New(&StructRUsageType);
79 0 : if (!result)
80 0 : return NULL;
81 :
82 0 : PyStructSequence_SET_ITEM(result, 0,
83 : PyFloat_FromDouble(doubletime(ru.ru_utime)));
84 0 : PyStructSequence_SET_ITEM(result, 1,
85 : PyFloat_FromDouble(doubletime(ru.ru_stime)));
86 0 : PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
87 0 : PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
88 0 : PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
89 0 : PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss));
90 0 : PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt));
91 0 : PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt));
92 0 : PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap));
93 0 : PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock));
94 0 : PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock));
95 0 : PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd));
96 0 : PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv));
97 0 : PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
98 0 : PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
99 0 : PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
100 :
101 0 : if (PyErr_Occurred()) {
102 0 : Py_DECREF(result);
103 0 : return NULL;
104 : }
105 :
106 0 : return result;
107 : }
108 :
109 :
110 : static PyObject *
111 0 : resource_getrlimit(PyObject *self, PyObject *args)
112 : {
113 : struct rlimit rl;
114 : int resource;
115 :
116 0 : if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))
117 0 : return NULL;
118 :
119 0 : if (resource < 0 || resource >= RLIM_NLIMITS) {
120 0 : PyErr_SetString(PyExc_ValueError,
121 : "invalid resource specified");
122 0 : return NULL;
123 : }
124 :
125 0 : if (getrlimit(resource, &rl) == -1) {
126 0 : PyErr_SetFromErrno(PyExc_OSError);
127 0 : return NULL;
128 : }
129 :
130 : #if defined(HAVE_LONG_LONG)
131 : if (sizeof(rl.rlim_cur) > sizeof(long)) {
132 0 : return Py_BuildValue("LL",
133 0 : (PY_LONG_LONG) rl.rlim_cur,
134 0 : (PY_LONG_LONG) rl.rlim_max);
135 : }
136 : #endif
137 : return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max);
138 : }
139 :
140 : static PyObject *
141 0 : resource_setrlimit(PyObject *self, PyObject *args)
142 : {
143 : struct rlimit rl;
144 : int resource;
145 : PyObject *curobj, *maxobj;
146 :
147 0 : if (!PyArg_ParseTuple(args, "i(OO):setrlimit",
148 : &resource, &curobj, &maxobj))
149 0 : return NULL;
150 :
151 0 : if (resource < 0 || resource >= RLIM_NLIMITS) {
152 0 : PyErr_SetString(PyExc_ValueError,
153 : "invalid resource specified");
154 0 : return NULL;
155 : }
156 :
157 : #if !defined(HAVE_LARGEFILE_SUPPORT)
158 : rl.rlim_cur = PyLong_AsLong(curobj);
159 : if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
160 : return NULL;
161 : rl.rlim_max = PyLong_AsLong(maxobj);
162 : if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())
163 : return NULL;
164 : #else
165 : /* The limits are probably bigger than a long */
166 0 : rl.rlim_cur = PyLong_AsLongLong(curobj);
167 0 : if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
168 0 : return NULL;
169 0 : rl.rlim_max = PyLong_AsLongLong(maxobj);
170 0 : if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())
171 0 : return NULL;
172 : #endif
173 :
174 0 : rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY;
175 0 : rl.rlim_max = rl.rlim_max & RLIM_INFINITY;
176 0 : if (setrlimit(resource, &rl) == -1) {
177 0 : if (errno == EINVAL)
178 0 : PyErr_SetString(PyExc_ValueError,
179 : "current limit exceeds maximum limit");
180 0 : else if (errno == EPERM)
181 0 : PyErr_SetString(PyExc_ValueError,
182 : "not allowed to raise maximum limit");
183 : else
184 0 : PyErr_SetFromErrno(PyExc_OSError);
185 0 : return NULL;
186 : }
187 0 : Py_INCREF(Py_None);
188 0 : return Py_None;
189 : }
190 :
191 : static PyObject *
192 0 : resource_getpagesize(PyObject *self, PyObject *unused)
193 : {
194 0 : long pagesize = 0;
195 : #if defined(HAVE_GETPAGESIZE)
196 0 : pagesize = getpagesize();
197 : #elif defined(HAVE_SYSCONF)
198 : #if defined(_SC_PAGE_SIZE)
199 : pagesize = sysconf(_SC_PAGE_SIZE);
200 : #else
201 : /* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */
202 : pagesize = sysconf(_SC_PAGESIZE);
203 : #endif
204 : #endif
205 0 : return Py_BuildValue("i", pagesize);
206 :
207 : }
208 :
209 : /* List of functions */
210 :
211 : static struct PyMethodDef
212 : resource_methods[] = {
213 : {"getrusage", resource_getrusage, METH_VARARGS},
214 : {"getrlimit", resource_getrlimit, METH_VARARGS},
215 : {"setrlimit", resource_setrlimit, METH_VARARGS},
216 : {"getpagesize", resource_getpagesize, METH_NOARGS},
217 : {NULL, NULL} /* sentinel */
218 : };
219 :
220 :
221 : /* Module initialization */
222 :
223 :
224 : static struct PyModuleDef resourcemodule = {
225 : PyModuleDef_HEAD_INIT,
226 : "resource",
227 : NULL,
228 : -1,
229 : resource_methods,
230 : NULL,
231 : NULL,
232 : NULL,
233 : NULL
234 : };
235 :
236 : PyMODINIT_FUNC
237 0 : PyInit_resource(void)
238 : {
239 : PyObject *m, *v;
240 :
241 : /* Create the module and add the functions */
242 0 : m = PyModule_Create(&resourcemodule);
243 0 : if (m == NULL)
244 0 : return NULL;
245 :
246 : /* Add some symbolic constants to the module */
247 0 : Py_INCREF(PyExc_OSError);
248 0 : PyModule_AddObject(m, "error", PyExc_OSError);
249 0 : if (!initialized)
250 0 : PyStructSequence_InitType(&StructRUsageType,
251 : &struct_rusage_desc);
252 0 : Py_INCREF(&StructRUsageType);
253 0 : PyModule_AddObject(m, "struct_rusage",
254 : (PyObject*) &StructRUsageType);
255 :
256 : /* insert constants */
257 : #ifdef RLIMIT_CPU
258 0 : PyModule_AddIntConstant(m, "RLIMIT_CPU", RLIMIT_CPU);
259 : #endif
260 :
261 : #ifdef RLIMIT_FSIZE
262 0 : PyModule_AddIntConstant(m, "RLIMIT_FSIZE", RLIMIT_FSIZE);
263 : #endif
264 :
265 : #ifdef RLIMIT_DATA
266 0 : PyModule_AddIntConstant(m, "RLIMIT_DATA", RLIMIT_DATA);
267 : #endif
268 :
269 : #ifdef RLIMIT_STACK
270 0 : PyModule_AddIntConstant(m, "RLIMIT_STACK", RLIMIT_STACK);
271 : #endif
272 :
273 : #ifdef RLIMIT_CORE
274 0 : PyModule_AddIntConstant(m, "RLIMIT_CORE", RLIMIT_CORE);
275 : #endif
276 :
277 : #ifdef RLIMIT_NOFILE
278 0 : PyModule_AddIntConstant(m, "RLIMIT_NOFILE", RLIMIT_NOFILE);
279 : #endif
280 :
281 : #ifdef RLIMIT_OFILE
282 0 : PyModule_AddIntConstant(m, "RLIMIT_OFILE", RLIMIT_OFILE);
283 : #endif
284 :
285 : #ifdef RLIMIT_VMEM
286 : PyModule_AddIntConstant(m, "RLIMIT_VMEM", RLIMIT_VMEM);
287 : #endif
288 :
289 : #ifdef RLIMIT_AS
290 0 : PyModule_AddIntConstant(m, "RLIMIT_AS", RLIMIT_AS);
291 : #endif
292 :
293 : #ifdef RLIMIT_RSS
294 0 : PyModule_AddIntConstant(m, "RLIMIT_RSS", RLIMIT_RSS);
295 : #endif
296 :
297 : #ifdef RLIMIT_NPROC
298 0 : PyModule_AddIntConstant(m, "RLIMIT_NPROC", RLIMIT_NPROC);
299 : #endif
300 :
301 : #ifdef RLIMIT_MEMLOCK
302 0 : PyModule_AddIntConstant(m, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
303 : #endif
304 :
305 : #ifdef RLIMIT_SBSIZE
306 : PyModule_AddIntConstant(m, "RLIMIT_SBSIZE", RLIMIT_SBSIZE);
307 : #endif
308 :
309 : #ifdef RUSAGE_SELF
310 0 : PyModule_AddIntConstant(m, "RUSAGE_SELF", RUSAGE_SELF);
311 : #endif
312 :
313 : #ifdef RUSAGE_CHILDREN
314 0 : PyModule_AddIntConstant(m, "RUSAGE_CHILDREN", RUSAGE_CHILDREN);
315 : #endif
316 :
317 : #ifdef RUSAGE_BOTH
318 : PyModule_AddIntConstant(m, "RUSAGE_BOTH", RUSAGE_BOTH);
319 : #endif
320 :
321 : #ifdef RUSAGE_THREAD
322 0 : PyModule_AddIntConstant(m, "RUSAGE_THREAD", RUSAGE_THREAD);
323 : #endif
324 :
325 : #if defined(HAVE_LONG_LONG)
326 : if (sizeof(RLIM_INFINITY) > sizeof(long)) {
327 0 : v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
328 : } else
329 : #endif
330 : {
331 : v = PyLong_FromLong((long) RLIM_INFINITY);
332 : }
333 0 : if (v) {
334 0 : PyModule_AddObject(m, "RLIM_INFINITY", v);
335 : }
336 0 : initialized = 1;
337 0 : return m;
338 : }
|