Where & how to deallocate resources in Python C extension


F

fredbasset1000

Hi,

I've written a C extension, see code below, to provide a Python
interface to a hardware watchdog timer. As part of the initialization
it makes some calls to mmap, I am wondering should I be making
balanced calls to munmap in some kind of de-init function? Do Python
extensions have d'tors?

Thanks for any help,
Fred

----------------------------------------------------------------------------------------------
#include <Python.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <errno.h>

static const uint8_t WD_PAT_VALUE = 0x05; // hard coded value to
indicate a pat to the watchdog

static uint8_t* wdt_control = NULL;
static uint8_t* wdt_feed = NULL;

/*!
\brief Initialize the watchdog timer and start it.

\param[in] int timeout_period, value to pass to timeout register
0x00 - 0x07, see table above.
\return void
*/
static PyObject* init(PyObject *self, PyObject *args) {
int period;
int fd;

if (!PyArg_Parse(args, "(i)", &period)) {
PyErr_SetString(PyExc_TypeError, "single integer argument
expected");
return NULL;
}
if (period <= 0x00 || period >= 0x07) {
PyErr_SetString(PyExc_ValueError, "watchdog reg. value out of
range (0x00 to 0x07 only)");
return NULL;
}

fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
PyErr_SetString(PyExc_SystemError, strerror(errno));
return NULL;
}
wdt_control = mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0x23800000);
if (wdt_control == MAP_FAILED) {
PyErr_SetString(PyExc_SystemError, strerror(errno));
return NULL;
}

wdt_feed = mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0x23C00000);
if (wdt_feed == MAP_FAILED) {
PyErr_SetString(PyExc_SystemError, strerror(errno));
return NULL;
}

*wdt_feed = WD_PAT_VALUE; // must first pat the w.d. before
setting period
*wdt_control = period;

Py_INCREF(Py_None);
return Py_None;
}

/*!
\brief Pat the watchdog timer once.
Always call init() before calling this function.

\return void
*/
static PyObject* pat(PyObject *self, PyObject *args)
{
if (!PyArg_Parse(args, "( )")) { // verify no args passed
return NULL;
}

if (wdt_feed != NULL) {
*wdt_feed = WD_PAT_VALUE;
}

Py_INCREF(Py_None);
return Py_None;
}

// method registration table
static struct PyMethodDef wdt_methods[] = {
{"init", init, METH_VARARGS},
{"pat", pat, METH_VARARGS},
{NULL, NULL}
};

// module initializer, called on first import
void initwdtmodule() {
(void) Py_InitModule("wdtmodule", wdt_methods);
}
 
Ad

Advertisements

G

Gabriel Genellina

I've written a C extension, see code below, to provide a Python
interface to a hardware watchdog timer. As part of the initialization
it makes some calls to mmap, I am wondering should I be making
balanced calls to munmap in some kind of de-init function? Do Python
extensions have d'tors?

No, there is no way to de-initialize an extension module. That's a big
deficiency.
In some cases you may provide your own function (and hope the users call
it when needed), or use Py_AtExit.
 
Ad

Advertisements

M

Mark Wooding

I've written a C extension, see code below, to provide a Python
interface to a hardware watchdog timer. As part of the initialization
it makes some calls to mmap, I am wondering should I be making
balanced calls to munmap in some kind of de-init function?

The kernel should remove the mapping when your process exits anyway --
otherwise the world would be left in an inconsistent state if your
process got killed by SIGKILL for example.
Do Python extensions have d'tors?

No. But you can cheat: stash some object whose tp_del slot does your
cleanup in your extension's module under some funny name. (And woe
betide anyone who dels the funny name prematurely!) I'm not sure I'd
bother.

-- [mdw]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top