resource.c 8.62 KB
Newer Older
1

2
#include "Python.h"
3
#include "structseq.h"
4 5 6 7
#include <sys/resource.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
8 9 10 11
/* for sysconf */
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
12

13 14 15 16 17 18
/* On some systems, these aren't in any header file.
   On others they are, with inconsistent prototypes.
   We declare the (default) return type, to shut up gcc -Wall;
   but we can't declare the prototype, to avoid errors
   when the header files declare it different.
   Worse, on some Linuxes, getpagesize() returns a size_t... */
19 20 21 22 23

#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)

static PyObject *ResourceError;

24 25 26 27 28 29
PyDoc_STRVAR(struct_rusage__doc__,
"struct_rusage: Result from getrusage.\n\n"
"This object may be accessed either as a tuple of\n"
"    (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n"
"    nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n"
"or via the attributes ru_utime, ru_stime, ru_maxrss, and so on.");
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57

static PyStructSequence_Field struct_rusage_fields[] = {
	{"ru_utime",	"user time used"},
	{"ru_stime",	"system time used"},
	{"ru_maxrss",	"max. resident set size"},
	{"ru_ixrss",	"shared memory size"},
	{"ru_idrss",	"unshared data size"},
	{"ru_isrss",	"unshared stack size"},
	{"ru_minflt",	"page faults not requiring I/O"},
	{"ru_majflt",	"page faults requiring I/O"},
	{"ru_nswap",	"number of swap outs"},
	{"ru_inblock",	"block input operations"},
	{"ru_oublock",	"block output operations"},
	{"ru_msgsnd",	"IPC messages sent"},
	{"ru_msgrcv",	"IPC messages received"},
	{"ru_nsignals",	"signals received"},
	{"ru_nvcsw",	"voluntary context switches"},
	{"ru_nivcsw",	"involuntary context switches"},
	{0}
};

static PyStructSequence_Desc struct_rusage_desc = {
	"resource.struct_rusage",	/* name */
	struct_rusage__doc__,	/* doc */
	struct_rusage_fields,	/* fields */
	16	/* n_in_sequence */
};

58
static int initialized;
59 60
static PyTypeObject StructRUsageType;

61
static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
62
resource_getrusage(PyObject *self, PyObject *args)
63 64 65
{
	int who;
	struct rusage ru;
66
	PyObject *result;
67

68
	if (!PyArg_ParseTuple(args, "i:getrusage", &who))
69 70 71 72 73 74 75 76 77 78 79 80
		return NULL;

	if (getrusage(who, &ru) == -1) {
		if (errno == EINVAL) {
			PyErr_SetString(PyExc_ValueError,
					"invalid who parameter");
			return NULL;
		} 
		PyErr_SetFromErrno(ResourceError);
		return NULL;
	}

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
	result = PyStructSequence_New(&StructRUsageType);
	if (!result)
		return NULL;

	PyStructSequence_SET_ITEM(result, 0,
			PyFloat_FromDouble(doubletime(ru.ru_utime)));
	PyStructSequence_SET_ITEM(result, 1,
			PyFloat_FromDouble(doubletime(ru.ru_stime)));
	PyStructSequence_SET_ITEM(result, 2, PyInt_FromLong(ru.ru_maxrss));
	PyStructSequence_SET_ITEM(result, 3, PyInt_FromLong(ru.ru_ixrss));
	PyStructSequence_SET_ITEM(result, 4, PyInt_FromLong(ru.ru_idrss));
	PyStructSequence_SET_ITEM(result, 5, PyInt_FromLong(ru.ru_isrss));
	PyStructSequence_SET_ITEM(result, 6, PyInt_FromLong(ru.ru_minflt));
	PyStructSequence_SET_ITEM(result, 7, PyInt_FromLong(ru.ru_majflt));
	PyStructSequence_SET_ITEM(result, 8, PyInt_FromLong(ru.ru_nswap));
	PyStructSequence_SET_ITEM(result, 9, PyInt_FromLong(ru.ru_inblock));
	PyStructSequence_SET_ITEM(result, 10, PyInt_FromLong(ru.ru_oublock));
	PyStructSequence_SET_ITEM(result, 11, PyInt_FromLong(ru.ru_msgsnd));
	PyStructSequence_SET_ITEM(result, 12, PyInt_FromLong(ru.ru_msgrcv));
	PyStructSequence_SET_ITEM(result, 13, PyInt_FromLong(ru.ru_nsignals));
	PyStructSequence_SET_ITEM(result, 14, PyInt_FromLong(ru.ru_nvcsw));
	PyStructSequence_SET_ITEM(result, 15, PyInt_FromLong(ru.ru_nivcsw));

	if (PyErr_Occurred()) {
		Py_DECREF(result);
		return NULL;
	}

	return result;
110 111 112 113
}


static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
114
resource_getrlimit(PyObject *self, PyObject *args)
115 116 117 118
{
	struct rlimit rl;
	int resource;

119
	if (!PyArg_ParseTuple(args, "i:getrlimit", &resource)) 
120 121 122 123 124 125 126 127 128 129 130 131
		return NULL;

	if (resource < 0 || resource >= RLIM_NLIMITS) {
		PyErr_SetString(PyExc_ValueError,
				"invalid resource specified");
		return NULL;
	}

	if (getrlimit(resource, &rl) == -1) {
		PyErr_SetFromErrno(ResourceError);
		return NULL;
	}
132 133 134 135

#if defined(HAVE_LONG_LONG)
	if (sizeof(rl.rlim_cur) > sizeof(long)) {
		return Py_BuildValue("LL",
136 137
				     (PY_LONG_LONG) rl.rlim_cur,
				     (PY_LONG_LONG) rl.rlim_max);
138 139
	}
#endif
140
	return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max);
141 142 143
}

static PyObject *
Peter Schneider-Kamp's avatar
Peter Schneider-Kamp committed
144
resource_setrlimit(PyObject *self, PyObject *args)
145 146 147
{
	struct rlimit rl;
	int resource;
148
	PyObject *curobj, *maxobj;
149

150
	if (!PyArg_ParseTuple(args, "i(OO):setrlimit",
151
			      &resource, &curobj, &maxobj))
152 153 154 155 156 157 158 159
		return NULL;

	if (resource < 0 || resource >= RLIM_NLIMITS) {
		PyErr_SetString(PyExc_ValueError,
				"invalid resource specified");
		return NULL;
	}

160 161
#if !defined(HAVE_LARGEFILE_SUPPORT)
	rl.rlim_cur = PyInt_AsLong(curobj);
162
	if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
163
	    return NULL;
164
	rl.rlim_max = PyInt_AsLong(maxobj);
165
	if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())
166
	    return NULL;
167 168 169 170
#else
	/* The limits are probably bigger than a long */
	rl.rlim_cur = PyLong_Check(curobj) ?
		PyLong_AsLongLong(curobj) : PyInt_AsLong(curobj);
171
	if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred())
172
	    return NULL;
173 174
	rl.rlim_max = PyLong_Check(maxobj) ?
		PyLong_AsLongLong(maxobj) : PyInt_AsLong(maxobj);
175
	if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred())
176
	    return NULL;
177 178
#endif

179 180 181
	rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY;
	rl.rlim_max = rl.rlim_max & RLIM_INFINITY;
	if (setrlimit(resource, &rl) == -1) {
182
		if (errno == EINVAL)
183 184 185 186 187 188 189 190 191 192 193 194 195 196
			PyErr_SetString(PyExc_ValueError,
					"current limit exceeds maximum limit");
		else if (errno == EPERM)
			PyErr_SetString(PyExc_ValueError,
					"not allowed to raise maximum limit");
		else
			PyErr_SetFromErrno(ResourceError);
		return NULL;
	}
	Py_INCREF(Py_None);
	return Py_None;
}

static PyObject *
197
resource_getpagesize(PyObject *self, PyObject *unused)
198
{
199
	long pagesize = 0;
200 201 202
#if defined(HAVE_GETPAGESIZE)
	pagesize = getpagesize();
#elif defined(HAVE_SYSCONF)
203
#if defined(_SC_PAGE_SIZE)
204
	pagesize = sysconf(_SC_PAGE_SIZE);
205 206 207 208
#else
	/* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */
	pagesize = sysconf(_SC_PAGESIZE);
#endif
209 210 211
#endif
	return Py_BuildValue("i", pagesize);

212 213 214 215 216 217
}

/* List of functions */

static struct PyMethodDef
resource_methods[] = {
218 219 220
	{"getrusage",    resource_getrusage,   METH_VARARGS},
	{"getrlimit",    resource_getrlimit,   METH_VARARGS},
	{"setrlimit",    resource_setrlimit,   METH_VARARGS},
221
	{"getpagesize",  resource_getpagesize, METH_NOARGS},
222 223 224 225 226 227
	{NULL, NULL}			     /* sentinel */
};


/* Module initialization */

228
PyMODINIT_FUNC
229
initresource(void)
230
{
231
	PyObject *m, *v;
232 233 234

	/* Create the module and add the functions */
	m = Py_InitModule("resource", resource_methods);
235 236
	if (m == NULL)
		return;
237 238

	/* Add some symbolic constants to the module */
239 240 241 242 243 244
	if (ResourceError == NULL) {
		ResourceError = PyErr_NewException("resource.error",
						   NULL, NULL);
	}
	Py_INCREF(ResourceError);
	PyModule_AddObject(m, "error", ResourceError);
245 246 247 248
	if (!initialized)
		PyStructSequence_InitType(&StructRUsageType, 
					  &struct_rusage_desc);
	Py_INCREF(&StructRUsageType);
249 250
 	PyModule_AddObject(m, "struct_rusage", 
			   (PyObject*) &StructRUsageType);
251 252 253

	/* insert constants */
#ifdef RLIMIT_CPU
254
	PyModule_AddIntConstant(m, "RLIMIT_CPU", RLIMIT_CPU);
255 256 257
#endif

#ifdef RLIMIT_FSIZE
258
	PyModule_AddIntConstant(m, "RLIMIT_FSIZE", RLIMIT_FSIZE);
259 260 261
#endif

#ifdef RLIMIT_DATA
262
	PyModule_AddIntConstant(m, "RLIMIT_DATA", RLIMIT_DATA);
263 264 265
#endif

#ifdef RLIMIT_STACK
266
	PyModule_AddIntConstant(m, "RLIMIT_STACK", RLIMIT_STACK);
267 268 269
#endif

#ifdef RLIMIT_CORE
270
	PyModule_AddIntConstant(m, "RLIMIT_CORE", RLIMIT_CORE);
271 272 273
#endif

#ifdef RLIMIT_NOFILE
274
	PyModule_AddIntConstant(m, "RLIMIT_NOFILE", RLIMIT_NOFILE);
275 276 277
#endif

#ifdef RLIMIT_OFILE
278
	PyModule_AddIntConstant(m, "RLIMIT_OFILE", RLIMIT_OFILE);
279 280 281
#endif

#ifdef RLIMIT_VMEM
282
	PyModule_AddIntConstant(m, "RLIMIT_VMEM", RLIMIT_VMEM);
283 284 285
#endif

#ifdef RLIMIT_AS
286
	PyModule_AddIntConstant(m, "RLIMIT_AS", RLIMIT_AS);
287 288 289
#endif

#ifdef RLIMIT_RSS
290
	PyModule_AddIntConstant(m, "RLIMIT_RSS", RLIMIT_RSS);
291 292 293
#endif

#ifdef RLIMIT_NPROC
294
	PyModule_AddIntConstant(m, "RLIMIT_NPROC", RLIMIT_NPROC);
295 296 297
#endif

#ifdef RLIMIT_MEMLOCK
298
	PyModule_AddIntConstant(m, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
299 300
#endif

301 302 303 304
#ifdef RLIMIT_SBSIZE
	PyModule_AddIntConstant(m, "RLIMIT_SBSIZE", RLIMIT_SBSIZE);
#endif

305
#ifdef RUSAGE_SELF
306
	PyModule_AddIntConstant(m, "RUSAGE_SELF", RUSAGE_SELF);
307 308
#endif

309
#ifdef RUSAGE_CHILDREN
310
	PyModule_AddIntConstant(m, "RUSAGE_CHILDREN", RUSAGE_CHILDREN);
311 312 313
#endif

#ifdef RUSAGE_BOTH
314
	PyModule_AddIntConstant(m, "RUSAGE_BOTH", RUSAGE_BOTH);
315
#endif
316 317 318

#if defined(HAVE_LONG_LONG)
	if (sizeof(RLIM_INFINITY) > sizeof(long)) {
319
		v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
320 321 322 323 324 325 326 327
	} else 
#endif
	{
		v = PyInt_FromLong((long) RLIM_INFINITY);
	}
	if (v) {
		PyModule_AddObject(m, "RLIM_INFINITY", v);
	}
328
	initialized = 1;
329
}