ยปCore Development>Code coverage>Modules/resource.c

Python code coverage for Modules/resource.c

#countcontent
1n/a
2n/a#include "Python.h"
3n/a#include <sys/resource.h>
4n/a#include <sys/time.h>
5n/a#include <string.h>
6n/a#include <errno.h>
7n/a/* for sysconf */
8n/a#if defined(HAVE_UNISTD_H)
9n/a#include <unistd.h>
10n/a#endif
11n/a
12n/a/* On some systems, these aren't in any header file.
13n/a On others they are, with inconsistent prototypes.
14n/a We declare the (default) return type, to shut up gcc -Wall;
15n/a but we can't declare the prototype, to avoid errors
16n/a when the header files declare it different.
17n/a Worse, on some Linuxes, getpagesize() returns a size_t... */
18n/a
19n/a#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
20n/a
21n/aPyDoc_STRVAR(struct_rusage__doc__,
22n/a"struct_rusage: Result from getrusage.\n\n"
23n/a"This object may be accessed either as a tuple of\n"
24n/a" (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n"
25n/a" nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n"
26n/a"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.");
27n/a
28n/astatic PyStructSequence_Field struct_rusage_fields[] = {
29n/a {"ru_utime", "user time used"},
30n/a {"ru_stime", "system time used"},
31n/a {"ru_maxrss", "max. resident set size"},
32n/a {"ru_ixrss", "shared memory size"},
33n/a {"ru_idrss", "unshared data size"},
34n/a {"ru_isrss", "unshared stack size"},
35n/a {"ru_minflt", "page faults not requiring I/O"},
36n/a {"ru_majflt", "page faults requiring I/O"},
37n/a {"ru_nswap", "number of swap outs"},
38n/a {"ru_inblock", "block input operations"},
39n/a {"ru_oublock", "block output operations"},
40n/a {"ru_msgsnd", "IPC messages sent"},
41n/a {"ru_msgrcv", "IPC messages received"},
42n/a {"ru_nsignals", "signals received"},
43n/a {"ru_nvcsw", "voluntary context switches"},
44n/a {"ru_nivcsw", "involuntary context switches"},
45n/a {0}
46n/a};
47n/a
48n/astatic PyStructSequence_Desc struct_rusage_desc = {
49n/a "resource.struct_rusage", /* name */
50n/a struct_rusage__doc__, /* doc */
51n/a struct_rusage_fields, /* fields */
52n/a 16 /* n_in_sequence */
53n/a};
54n/a
55n/astatic int initialized;
56n/astatic PyTypeObject StructRUsageType;
57n/a
58n/astatic PyObject *
59n/aresource_getrusage(PyObject *self, PyObject *args)
60n/a{
61n/a int who;
62n/a struct rusage ru;
63n/a PyObject *result;
64n/a
65n/a if (!PyArg_ParseTuple(args, "i:getrusage", &who))
66n/a return NULL;
67n/a
68n/a if (getrusage(who, &ru) == -1) {
69n/a if (errno == EINVAL) {
70n/a PyErr_SetString(PyExc_ValueError,
71n/a "invalid who parameter");
72n/a return NULL;
73n/a }
74n/a PyErr_SetFromErrno(PyExc_OSError);
75n/a return NULL;
76n/a }
77n/a
78n/a result = PyStructSequence_New(&StructRUsageType);
79n/a if (!result)
80n/a return NULL;
81n/a
82n/a PyStructSequence_SET_ITEM(result, 0,
83n/a PyFloat_FromDouble(doubletime(ru.ru_utime)));
84n/a PyStructSequence_SET_ITEM(result, 1,
85n/a PyFloat_FromDouble(doubletime(ru.ru_stime)));
86n/a PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
87n/a PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
88n/a PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
89n/a PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss));
90n/a PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt));
91n/a PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt));
92n/a PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap));
93n/a PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock));
94n/a PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock));
95n/a PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd));
96n/a PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv));
97n/a PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
98n/a PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
99n/a PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
100n/a
101n/a if (PyErr_Occurred()) {
102n/a Py_DECREF(result);
103n/a return NULL;
104n/a }
105n/a
106n/a return result;
107n/a}
108n/a
109n/astatic int
110n/apy2rlimit(PyObject *limits, struct rlimit *rl_out)
111n/a{
112n/a PyObject *curobj, *maxobj;
113n/a limits = PySequence_Tuple(limits);
114n/a if (!limits)
115n/a /* Here limits is a borrowed reference */
116n/a return -1;
117n/a
118n/a if (PyTuple_GET_SIZE(limits) != 2) {
119n/a PyErr_SetString(PyExc_ValueError,
120n/a "expected a tuple of 2 integers");
121n/a goto error;
122n/a }
123n/a curobj = PyTuple_GET_ITEM(limits, 0);
124n/a maxobj = PyTuple_GET_ITEM(limits, 1);
125n/a#if !defined(HAVE_LARGEFILE_SUPPORT)
126n/a rl_out->rlim_cur = PyLong_AsLong(curobj);
127n/a if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
128n/a goto error;
129n/a rl_out->rlim_max = PyLong_AsLong(maxobj);
130n/a if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
131n/a goto error;
132n/a#else
133n/a /* The limits are probably bigger than a long */
134n/a rl_out->rlim_cur = PyLong_AsLongLong(curobj);
135n/a if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
136n/a goto error;
137n/a rl_out->rlim_max = PyLong_AsLongLong(maxobj);
138n/a if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
139n/a goto error;
140n/a#endif
141n/a
142n/a Py_DECREF(limits);
143n/a rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY;
144n/a rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY;
145n/a return 0;
146n/a
147n/aerror:
148n/a Py_DECREF(limits);
149n/a return -1;
150n/a}
151n/a
152n/astatic PyObject*
153n/arlimit2py(struct rlimit rl)
154n/a{
155n/a if (sizeof(rl.rlim_cur) > sizeof(long)) {
156n/a return Py_BuildValue("LL",
157n/a (long long) rl.rlim_cur,
158n/a (long long) rl.rlim_max);
159n/a }
160n/a return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max);
161n/a}
162n/a
163n/astatic PyObject *
164n/aresource_getrlimit(PyObject *self, PyObject *args)
165n/a{
166n/a struct rlimit rl;
167n/a int resource;
168n/a
169n/a if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))
170n/a return NULL;
171n/a
172n/a if (resource < 0 || resource >= RLIM_NLIMITS) {
173n/a PyErr_SetString(PyExc_ValueError,
174n/a "invalid resource specified");
175n/a return NULL;
176n/a }
177n/a
178n/a if (getrlimit(resource, &rl) == -1) {
179n/a PyErr_SetFromErrno(PyExc_OSError);
180n/a return NULL;
181n/a }
182n/a return rlimit2py(rl);
183n/a}
184n/a
185n/astatic PyObject *
186n/aresource_setrlimit(PyObject *self, PyObject *args)
187n/a{
188n/a struct rlimit rl;
189n/a int resource;
190n/a PyObject *limits;
191n/a
192n/a if (!PyArg_ParseTuple(args, "iO:setrlimit", &resource, &limits))
193n/a return NULL;
194n/a
195n/a if (resource < 0 || resource >= RLIM_NLIMITS) {
196n/a PyErr_SetString(PyExc_ValueError,
197n/a "invalid resource specified");
198n/a return NULL;
199n/a }
200n/a
201n/a if (py2rlimit(limits, &rl) < 0) {
202n/a return NULL;
203n/a }
204n/a
205n/a if (setrlimit(resource, &rl) == -1) {
206n/a if (errno == EINVAL)
207n/a PyErr_SetString(PyExc_ValueError,
208n/a "current limit exceeds maximum limit");
209n/a else if (errno == EPERM)
210n/a PyErr_SetString(PyExc_ValueError,
211n/a "not allowed to raise maximum limit");
212n/a else
213n/a PyErr_SetFromErrno(PyExc_OSError);
214n/a return NULL;
215n/a }
216n/a Py_RETURN_NONE;
217n/a}
218n/a
219n/a#ifdef HAVE_PRLIMIT
220n/astatic PyObject *
221n/aresource_prlimit(PyObject *self, PyObject *args)
222n/a{
223n/a struct rlimit old_limit, new_limit;
224n/a int resource, retval;
225n/a pid_t pid;
226n/a PyObject *limits = NULL;
227n/a
228n/a if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i|O:prlimit",
229n/a &pid, &resource, &limits))
230n/a return NULL;
231n/a
232n/a if (resource < 0 || resource >= RLIM_NLIMITS) {
233n/a PyErr_SetString(PyExc_ValueError,
234n/a "invalid resource specified");
235n/a return NULL;
236n/a }
237n/a
238n/a if (limits != NULL) {
239n/a if (py2rlimit(limits, &new_limit) < 0) {
240n/a return NULL;
241n/a }
242n/a retval = prlimit(pid, resource, &new_limit, &old_limit);
243n/a }
244n/a else {
245n/a retval = prlimit(pid, resource, NULL, &old_limit);
246n/a }
247n/a
248n/a if (retval == -1) {
249n/a if (errno == EINVAL) {
250n/a PyErr_SetString(PyExc_ValueError,
251n/a "current limit exceeds maximum limit");
252n/a } else {
253n/a PyErr_SetFromErrno(PyExc_OSError);
254n/a }
255n/a return NULL;
256n/a }
257n/a return rlimit2py(old_limit);
258n/a}
259n/a#endif /* HAVE_PRLIMIT */
260n/a
261n/astatic PyObject *
262n/aresource_getpagesize(PyObject *self, PyObject *unused)
263n/a{
264n/a long pagesize = 0;
265n/a#if defined(HAVE_GETPAGESIZE)
266n/a pagesize = getpagesize();
267n/a#elif defined(HAVE_SYSCONF)
268n/a#if defined(_SC_PAGE_SIZE)
269n/a pagesize = sysconf(_SC_PAGE_SIZE);
270n/a#else
271n/a /* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */
272n/a pagesize = sysconf(_SC_PAGESIZE);
273n/a#endif
274n/a#endif
275n/a return Py_BuildValue("i", pagesize);
276n/a
277n/a}
278n/a
279n/a/* List of functions */
280n/a
281n/astatic struct PyMethodDef
282n/aresource_methods[] = {
283n/a {"getrusage", resource_getrusage, METH_VARARGS},
284n/a {"getrlimit", resource_getrlimit, METH_VARARGS},
285n/a#ifdef HAVE_PRLIMIT
286n/a {"prlimit", resource_prlimit, METH_VARARGS},
287n/a#endif
288n/a {"setrlimit", resource_setrlimit, METH_VARARGS},
289n/a {"getpagesize", resource_getpagesize, METH_NOARGS},
290n/a {NULL, NULL} /* sentinel */
291n/a};
292n/a
293n/a
294n/a/* Module initialization */
295n/a
296n/a
297n/astatic struct PyModuleDef resourcemodule = {
298n/a PyModuleDef_HEAD_INIT,
299n/a "resource",
300n/a NULL,
301n/a -1,
302n/a resource_methods,
303n/a NULL,
304n/a NULL,
305n/a NULL,
306n/a NULL
307n/a};
308n/a
309n/aPyMODINIT_FUNC
310n/aPyInit_resource(void)
311n/a{
312n/a PyObject *m, *v;
313n/a
314n/a /* Create the module and add the functions */
315n/a m = PyModule_Create(&resourcemodule);
316n/a if (m == NULL)
317n/a return NULL;
318n/a
319n/a /* Add some symbolic constants to the module */
320n/a Py_INCREF(PyExc_OSError);
321n/a PyModule_AddObject(m, "error", PyExc_OSError);
322n/a if (!initialized) {
323n/a if (PyStructSequence_InitType2(&StructRUsageType,
324n/a &struct_rusage_desc) < 0)
325n/a return NULL;
326n/a }
327n/a
328n/a Py_INCREF(&StructRUsageType);
329n/a PyModule_AddObject(m, "struct_rusage",
330n/a (PyObject*) &StructRUsageType);
331n/a
332n/a /* insert constants */
333n/a#ifdef RLIMIT_CPU
334n/a PyModule_AddIntMacro(m, RLIMIT_CPU);
335n/a#endif
336n/a
337n/a#ifdef RLIMIT_FSIZE
338n/a PyModule_AddIntMacro(m, RLIMIT_FSIZE);
339n/a#endif
340n/a
341n/a#ifdef RLIMIT_DATA
342n/a PyModule_AddIntMacro(m, RLIMIT_DATA);
343n/a#endif
344n/a
345n/a#ifdef RLIMIT_STACK
346n/a PyModule_AddIntMacro(m, RLIMIT_STACK);
347n/a#endif
348n/a
349n/a#ifdef RLIMIT_CORE
350n/a PyModule_AddIntMacro(m, RLIMIT_CORE);
351n/a#endif
352n/a
353n/a#ifdef RLIMIT_NOFILE
354n/a PyModule_AddIntMacro(m, RLIMIT_NOFILE);
355n/a#endif
356n/a
357n/a#ifdef RLIMIT_OFILE
358n/a PyModule_AddIntMacro(m, RLIMIT_OFILE);
359n/a#endif
360n/a
361n/a#ifdef RLIMIT_VMEM
362n/a PyModule_AddIntMacro(m, RLIMIT_VMEM);
363n/a#endif
364n/a
365n/a#ifdef RLIMIT_AS
366n/a PyModule_AddIntMacro(m, RLIMIT_AS);
367n/a#endif
368n/a
369n/a#ifdef RLIMIT_RSS
370n/a PyModule_AddIntMacro(m, RLIMIT_RSS);
371n/a#endif
372n/a
373n/a#ifdef RLIMIT_NPROC
374n/a PyModule_AddIntMacro(m, RLIMIT_NPROC);
375n/a#endif
376n/a
377n/a#ifdef RLIMIT_MEMLOCK
378n/a PyModule_AddIntMacro(m, RLIMIT_MEMLOCK);
379n/a#endif
380n/a
381n/a#ifdef RLIMIT_SBSIZE
382n/a PyModule_AddIntMacro(m, RLIMIT_SBSIZE);
383n/a#endif
384n/a
385n/a/* Linux specific */
386n/a#ifdef RLIMIT_MSGQUEUE
387n/a PyModule_AddIntMacro(m, RLIMIT_MSGQUEUE);
388n/a#endif
389n/a
390n/a#ifdef RLIMIT_NICE
391n/a PyModule_AddIntMacro(m, RLIMIT_NICE);
392n/a#endif
393n/a
394n/a#ifdef RLIMIT_RTPRIO
395n/a PyModule_AddIntMacro(m, RLIMIT_RTPRIO);
396n/a#endif
397n/a
398n/a#ifdef RLIMIT_RTTIME
399n/a PyModule_AddIntMacro(m, RLIMIT_RTTIME);
400n/a#endif
401n/a
402n/a#ifdef RLIMIT_SIGPENDING
403n/a PyModule_AddIntMacro(m, RLIMIT_SIGPENDING);
404n/a#endif
405n/a
406n/a/* target */
407n/a#ifdef RUSAGE_SELF
408n/a PyModule_AddIntMacro(m, RUSAGE_SELF);
409n/a#endif
410n/a
411n/a#ifdef RUSAGE_CHILDREN
412n/a PyModule_AddIntMacro(m, RUSAGE_CHILDREN);
413n/a#endif
414n/a
415n/a#ifdef RUSAGE_BOTH
416n/a PyModule_AddIntMacro(m, RUSAGE_BOTH);
417n/a#endif
418n/a
419n/a#ifdef RUSAGE_THREAD
420n/a PyModule_AddIntMacro(m, RUSAGE_THREAD);
421n/a#endif
422n/a
423n/a/* FreeBSD specific */
424n/a
425n/a#ifdef RLIMIT_SWAP
426n/a PyModule_AddIntMacro(m, RLIMIT_SWAP);
427n/a#endif
428n/a
429n/a#ifdef RLIMIT_SBSIZE
430n/a PyModule_AddIntMacro(m, RLIMIT_SBSIZE);
431n/a#endif
432n/a
433n/a#ifdef RLIMIT_NPTS
434n/a PyModule_AddIntMacro(m, RLIMIT_NPTS);
435n/a#endif
436n/a
437n/a if (sizeof(RLIM_INFINITY) > sizeof(long)) {
438n/a v = PyLong_FromLongLong((long long) RLIM_INFINITY);
439n/a } else
440n/a {
441n/a v = PyLong_FromLong((long) RLIM_INFINITY);
442n/a }
443n/a if (v) {
444n/a PyModule_AddObject(m, "RLIM_INFINITY", v);
445n/a }
446n/a initialized = 1;
447n/a return m;
448n/a}