~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Modules/resource.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
resource_getrusage(PyObject *self, PyObject *args)
 
60
{
 
61
    int who;
 
62
    struct rusage ru;
 
63
    PyObject *result;
 
64
 
 
65
    if (!PyArg_ParseTuple(args, "i:getrusage", &who))
 
66
        return NULL;
 
67
 
 
68
    if (getrusage(who, &ru) == -1) {
 
69
        if (errno == EINVAL) {
 
70
            PyErr_SetString(PyExc_ValueError,
 
71
                            "invalid who parameter");
 
72
            return NULL;
 
73
        }
 
74
        PyErr_SetFromErrno(PyExc_OSError);
 
75
        return NULL;
 
76
    }
 
77
 
 
78
    result = PyStructSequence_New(&StructRUsageType);
 
79
    if (!result)
 
80
        return NULL;
 
81
 
 
82
    PyStructSequence_SET_ITEM(result, 0,
 
83
                    PyFloat_FromDouble(doubletime(ru.ru_utime)));
 
84
    PyStructSequence_SET_ITEM(result, 1,
 
85
                    PyFloat_FromDouble(doubletime(ru.ru_stime)));
 
86
    PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss));
 
87
    PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss));
 
88
    PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss));
 
89
    PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss));
 
90
    PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt));
 
91
    PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt));
 
92
    PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap));
 
93
    PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock));
 
94
    PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock));
 
95
    PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd));
 
96
    PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv));
 
97
    PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals));
 
98
    PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw));
 
99
    PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw));
 
100
 
 
101
    if (PyErr_Occurred()) {
 
102
        Py_DECREF(result);
 
103
        return NULL;
 
104
    }
 
105
 
 
106
    return result;
 
107
}
 
108
 
 
109
static int
 
110
py2rlimit(PyObject *curobj, PyObject *maxobj, struct rlimit *rl_out)
 
111
{
 
112
#if !defined(HAVE_LARGEFILE_SUPPORT)
 
113
    rl_out->rlim_cur = PyLong_AsLong(curobj);
 
114
    if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
 
115
        return -1;
 
116
    rl_out->rlim_max = PyLong_AsLong(maxobj);
 
117
    if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
 
118
        return -1;
 
119
#else
 
120
    /* The limits are probably bigger than a long */
 
121
    rl_out->rlim_cur = PyLong_AsLongLong(curobj);
 
122
    if (rl_out->rlim_cur == (rlim_t)-1 && PyErr_Occurred())
 
123
        return -1;
 
124
    rl_out->rlim_max = PyLong_AsLongLong(maxobj);
 
125
    if (rl_out->rlim_max == (rlim_t)-1 && PyErr_Occurred())
 
126
        return -1;
 
127
#endif
 
128
 
 
129
    rl_out->rlim_cur = rl_out->rlim_cur & RLIM_INFINITY;
 
130
    rl_out->rlim_max = rl_out->rlim_max & RLIM_INFINITY;
 
131
    return 0;
 
132
 
 
133
}
 
134
 
 
135
static PyObject*
 
136
rlimit2py(struct rlimit rl)
 
137
{
 
138
#if defined(HAVE_LONG_LONG)
 
139
    if (sizeof(rl.rlim_cur) > sizeof(long)) {
 
140
        return Py_BuildValue("LL",
 
141
                             (PY_LONG_LONG) rl.rlim_cur,
 
142
                             (PY_LONG_LONG) rl.rlim_max);
 
143
    }
 
144
#endif
 
145
    return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max);
 
146
}
 
147
 
 
148
static PyObject *
 
149
resource_getrlimit(PyObject *self, PyObject *args)
 
150
{
 
151
    struct rlimit rl;
 
152
    int resource;
 
153
 
 
154
    if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))
 
155
        return NULL;
 
156
 
 
157
    if (resource < 0 || resource >= RLIM_NLIMITS) {
 
158
        PyErr_SetString(PyExc_ValueError,
 
159
                        "invalid resource specified");
 
160
        return NULL;
 
161
    }
 
162
 
 
163
    if (getrlimit(resource, &rl) == -1) {
 
164
        PyErr_SetFromErrno(PyExc_OSError);
 
165
        return NULL;
 
166
    }
 
167
    return rlimit2py(rl);
 
168
}
 
169
 
 
170
static PyObject *
 
171
resource_setrlimit(PyObject *self, PyObject *args)
 
172
{
 
173
    struct rlimit rl;
 
174
    int resource;
 
175
    PyObject *limits, *curobj, *maxobj;
 
176
 
 
177
    if (!PyArg_ParseTuple(args, "iO:setrlimit", &resource, &limits))
 
178
        return NULL;
 
179
 
 
180
    if (resource < 0 || resource >= RLIM_NLIMITS) {
 
181
        PyErr_SetString(PyExc_ValueError,
 
182
                        "invalid resource specified");
 
183
        return NULL;
 
184
    }
 
185
 
 
186
    limits = PySequence_Tuple(limits);
 
187
    if (!limits)
 
188
        /* Here limits is a borrowed reference */
 
189
        return NULL;
 
190
 
 
191
    if (PyTuple_GET_SIZE(limits) != 2) {
 
192
        PyErr_SetString(PyExc_ValueError,
 
193
                        "expected a tuple of 2 integers");
 
194
        goto error;
 
195
    }
 
196
    curobj = PyTuple_GET_ITEM(limits, 0);
 
197
    maxobj = PyTuple_GET_ITEM(limits, 1);
 
198
 
 
199
    if (py2rlimit(curobj, maxobj, &rl) < 0) {
 
200
        goto error;
 
201
    }
 
202
 
 
203
    if (setrlimit(resource, &rl) == -1) {
 
204
        if (errno == EINVAL)
 
205
            PyErr_SetString(PyExc_ValueError,
 
206
                            "current limit exceeds maximum limit");
 
207
        else if (errno == EPERM)
 
208
            PyErr_SetString(PyExc_ValueError,
 
209
                            "not allowed to raise maximum limit");
 
210
        else
 
211
            PyErr_SetFromErrno(PyExc_OSError);
 
212
        goto error;
 
213
    }
 
214
    Py_DECREF(limits);
 
215
    Py_INCREF(Py_None);
 
216
    return Py_None;
 
217
 
 
218
  error:
 
219
    Py_DECREF(limits);
 
220
    return NULL;
 
221
}
 
222
 
 
223
#ifdef HAVE_PRLIMIT
 
224
static PyObject *
 
225
resource_prlimit(PyObject *self, PyObject *args)
 
226
{
 
227
    struct rlimit old_limit, new_limit;
 
228
    int resource, retval;
 
229
    pid_t pid;
 
230
    PyObject *curobj=NULL, *maxobj=NULL;
 
231
 
 
232
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i|(OO):prlimit",
 
233
                          &pid, &resource, &curobj, &maxobj))
 
234
        return NULL;
 
235
 
 
236
    if (resource < 0 || resource >= RLIM_NLIMITS) {
 
237
        PyErr_SetString(PyExc_ValueError,
 
238
                        "invalid resource specified");
 
239
        return NULL;
 
240
    }
 
241
 
 
242
    if (curobj != NULL) {
 
243
        if (py2rlimit(curobj, maxobj, &new_limit) < 0) {
 
244
            return NULL;
 
245
        }
 
246
        retval = prlimit(pid, resource, &new_limit, &old_limit);
 
247
    }
 
248
    else {
 
249
        retval = prlimit(pid, resource, NULL, &old_limit);
 
250
    }
 
251
 
 
252
    if (retval == -1) {
 
253
        if (errno == EINVAL) {
 
254
            PyErr_SetString(PyExc_ValueError,
 
255
                            "current limit exceeds maximum limit");
 
256
        } else {
 
257
            PyErr_SetFromErrno(PyExc_OSError);
 
258
        }
 
259
        return NULL;
 
260
    }
 
261
    return rlimit2py(old_limit);
 
262
}
 
263
#endif /* HAVE_PRLIMIT */
 
264
 
 
265
static PyObject *
 
266
resource_getpagesize(PyObject *self, PyObject *unused)
 
267
{
 
268
    long pagesize = 0;
 
269
#if defined(HAVE_GETPAGESIZE)
 
270
    pagesize = getpagesize();
 
271
#elif defined(HAVE_SYSCONF)
 
272
#if defined(_SC_PAGE_SIZE)
 
273
    pagesize = sysconf(_SC_PAGE_SIZE);
 
274
#else
 
275
    /* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */
 
276
    pagesize = sysconf(_SC_PAGESIZE);
 
277
#endif
 
278
#endif
 
279
    return Py_BuildValue("i", pagesize);
 
280
 
 
281
}
 
282
 
 
283
/* List of functions */
 
284
 
 
285
static struct PyMethodDef
 
286
resource_methods[] = {
 
287
    {"getrusage",    resource_getrusage,   METH_VARARGS},
 
288
    {"getrlimit",    resource_getrlimit,   METH_VARARGS},
 
289
#ifdef HAVE_PRLIMIT
 
290
    {"prlimit",      resource_prlimit,     METH_VARARGS},
 
291
#endif
 
292
    {"setrlimit",    resource_setrlimit,   METH_VARARGS},
 
293
    {"getpagesize",  resource_getpagesize, METH_NOARGS},
 
294
    {NULL, NULL}                             /* sentinel */
 
295
};
 
296
 
 
297
 
 
298
/* Module initialization */
 
299
 
 
300
 
 
301
static struct PyModuleDef resourcemodule = {
 
302
    PyModuleDef_HEAD_INIT,
 
303
    "resource",
 
304
    NULL,
 
305
    -1,
 
306
    resource_methods,
 
307
    NULL,
 
308
    NULL,
 
309
    NULL,
 
310
    NULL
 
311
};
 
312
 
 
313
PyMODINIT_FUNC
 
314
PyInit_resource(void)
 
315
{
 
316
    PyObject *m, *v;
 
317
 
 
318
    /* Create the module and add the functions */
 
319
    m = PyModule_Create(&resourcemodule);
 
320
    if (m == NULL)
 
321
        return NULL;
 
322
 
 
323
    /* Add some symbolic constants to the module */
 
324
    Py_INCREF(PyExc_OSError);
 
325
    PyModule_AddObject(m, "error", PyExc_OSError);
 
326
    if (!initialized) {
 
327
        if (PyStructSequence_InitType2(&StructRUsageType,
 
328
                                       &struct_rusage_desc) < 0)
 
329
            return NULL;
 
330
    }
 
331
 
 
332
    Py_INCREF(&StructRUsageType);
 
333
    PyModule_AddObject(m, "struct_rusage",
 
334
                       (PyObject*) &StructRUsageType);
 
335
 
 
336
    /* insert constants */
 
337
#ifdef RLIMIT_CPU
 
338
    PyModule_AddIntMacro(m, RLIMIT_CPU);
 
339
#endif
 
340
 
 
341
#ifdef RLIMIT_FSIZE
 
342
    PyModule_AddIntMacro(m, RLIMIT_FSIZE);
 
343
#endif
 
344
 
 
345
#ifdef RLIMIT_DATA
 
346
    PyModule_AddIntMacro(m, RLIMIT_DATA);
 
347
#endif
 
348
 
 
349
#ifdef RLIMIT_STACK
 
350
    PyModule_AddIntMacro(m, RLIMIT_STACK);
 
351
#endif
 
352
 
 
353
#ifdef RLIMIT_CORE
 
354
    PyModule_AddIntMacro(m, RLIMIT_CORE);
 
355
#endif
 
356
 
 
357
#ifdef RLIMIT_NOFILE
 
358
    PyModule_AddIntMacro(m, RLIMIT_NOFILE);
 
359
#endif
 
360
 
 
361
#ifdef RLIMIT_OFILE
 
362
    PyModule_AddIntMacro(m, RLIMIT_OFILE);
 
363
#endif
 
364
 
 
365
#ifdef RLIMIT_VMEM
 
366
    PyModule_AddIntMacro(m, RLIMIT_VMEM);
 
367
#endif
 
368
 
 
369
#ifdef RLIMIT_AS
 
370
    PyModule_AddIntMacro(m, RLIMIT_AS);
 
371
#endif
 
372
 
 
373
#ifdef RLIMIT_RSS
 
374
    PyModule_AddIntMacro(m, RLIMIT_RSS);
 
375
#endif
 
376
 
 
377
#ifdef RLIMIT_NPROC
 
378
    PyModule_AddIntMacro(m, RLIMIT_NPROC);
 
379
#endif
 
380
 
 
381
#ifdef RLIMIT_MEMLOCK
 
382
    PyModule_AddIntMacro(m, RLIMIT_MEMLOCK);
 
383
#endif
 
384
 
 
385
#ifdef RLIMIT_SBSIZE
 
386
    PyModule_AddIntMacro(m, RLIMIT_SBSIZE);
 
387
#endif
 
388
 
 
389
/* Linux specific */
 
390
#ifdef RLIMIT_MSGQUEUE
 
391
    PyModule_AddIntMacro(m, RLIMIT_MSGQUEUE);
 
392
#endif
 
393
 
 
394
#ifdef RLIMIT_NICE
 
395
    PyModule_AddIntMacro(m, RLIMIT_NICE);
 
396
#endif
 
397
 
 
398
#ifdef RLIMIT_RTPRIO
 
399
    PyModule_AddIntMacro(m, RLIMIT_RTPRIO);
 
400
#endif
 
401
 
 
402
#ifdef RLIMIT_RTTIME
 
403
    PyModule_AddIntMacro(m, RLIMIT_RTTIME);
 
404
#endif
 
405
 
 
406
#ifdef RLIMIT_SIGPENDING
 
407
    PyModule_AddIntMacro(m, RLIMIT_SIGPENDING);
 
408
#endif
 
409
 
 
410
/* target */
 
411
#ifdef RUSAGE_SELF
 
412
    PyModule_AddIntMacro(m, RUSAGE_SELF);
 
413
#endif
 
414
 
 
415
#ifdef RUSAGE_CHILDREN
 
416
    PyModule_AddIntMacro(m, RUSAGE_CHILDREN);
 
417
#endif
 
418
 
 
419
#ifdef RUSAGE_BOTH
 
420
    PyModule_AddIntMacro(m, RUSAGE_BOTH);
 
421
#endif
 
422
 
 
423
#ifdef RUSAGE_THREAD
 
424
    PyModule_AddIntMacro(m, RUSAGE_THREAD);
 
425
#endif
 
426
 
 
427
#if defined(HAVE_LONG_LONG)
 
428
    if (sizeof(RLIM_INFINITY) > sizeof(long)) {
 
429
        v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
 
430
    } else
 
431
#endif
 
432
    {
 
433
        v = PyLong_FromLong((long) RLIM_INFINITY);
 
434
    }
 
435
    if (v) {
 
436
        PyModule_AddObject(m, "RLIM_INFINITY", v);
 
437
    }
 
438
    initialized = 1;
 
439
    return m;
 
440
}