Commits

Anonymous committed 5d08226

Fixed a memleak: Event is now a GC-enabled class and it tracks reference to callback and EventBase properly.

  • Participants
  • Parent commits 2ef6133

Comments (0)

Files changed (1)

File libevent/eventmodule.c

 static PyTypeObject Event_Type;
 
 /* EventObject prototypes */
-static PyObject *Event_New(PyTypeObject *, PyObject *, PyObject *);
 static int Event_Init(EventObject *, PyObject *, PyObject *);
 
 /* Singleton default event base */
 { 
     EventObject *newEvent = NULL;
 
-    newEvent = (EventObject *)Event_New(&Event_Type,NULL,NULL);
+    newEvent = (EventObject *)PyObject_GC_New(EventObject, &Event_Type);
 
     if (Event_Init(newEvent, args, kwargs) < 0)
 	return NULL;
     return ((o->ob_type) == &Event_Type);
 }
 
-/* Construct a new EventObject */
-static PyObject *Event_New(PyTypeObject *type, PyObject *args, 
-			   PyObject *kwargs) 
-{
-    EventObject *self = NULL;
-    assert(type != NULL && type->tp_alloc != NULL);
-    self = (EventObject *)type->tp_alloc(type, 0);
-    self->eventBase = NULL;
-    return (PyObject *)self;
-}
-
 /* Callback thunk. */
 static void __libevent_ev_callback(int fd, short events, void *arg) {
     EventObject    *ev = arg;
     PyTuple_SET_ITEM(tuple, 2, (PyObject *) ev);
     Py_INCREF((PyObject *) ev);
     result = PyObject_Call(ev->callback, tuple, NULL);
-    Py_DECREF((PyObject *) ev);
-    //Py_DECREF(tuple);
+    Py_DECREF(tuple);
     if (result) { 
 	Py_DECREF(result);
     }
     
     Py_INCREF(callback);
     self->callback = callback;
+    self->eventBase = NULL;
+    PyObject_GC_Track(self);
     return 0;
 }	
 
     return PyInt_FromLong(self->ev.ev_fd);
 }
 
+/* EventObject clearer */
+static int Event_clear(EventObject *self) {
+    Py_CLEAR(self->eventBase);
+    Py_CLEAR(self->callback);
+    return 0;
+}
 
 /* EventObject destructor */
 static void Event_Dealloc(EventObject *obj) { 
-    Py_XDECREF(obj->eventBase);
-    Py_XDECREF(obj->callback);
+    PyObject_GC_UnTrack((PyObject *)obj);
+    Event_clear(obj);
     obj->ob_type->tp_free((PyObject *)obj);
 }	
 
+/* EventObject traverse function */
+static int Event_traverse(EventObject *self, visitproc visit, void *arg) {
+    Py_VISIT(self->eventBase);
+    Py_VISIT(self->callback);
+    return 0;
+}
+
+
 static PyObject *Event_Repr(EventObject *self) {
 	char            buf[512];
 	PyOS_snprintf(buf, sizeof(buf),
     PyObject_GenericGetAttr,                   /*tp_getattro*/
     PyObject_GenericSetAttr,                   /*tp_setattro*/
     0,                                         /*tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE \
+        | Py_TPFLAGS_HAVE_GC,                  /*tp_flags*/
     0,                                         /*tp_doc*/
-    0,                                         /*tp_traverse*/
-    0,                                         /*tp_clear*/
+    (traverseproc)Event_traverse,              /*tp_traverse*/
+    (inquiry)Event_clear,                      /*tp_clear*/
     0,                                         /*tp_richcompare*/
     0,                                         /*tp_weaklistoffset*/
     0,                                         /*tp_iter*/
     0,                                         /*tp_descr_set*/
     0,                                         /*tp_dictoffset*/
     (initproc)Event_Init,                      /*tp_init*/
-    PyType_GenericAlloc,                       /*tp_alloc*/
-    Event_New,                                 /*tp_new*/
-    PyObject_Del,                              /*tp_free*/
-    0,                                         /*tp_is_gc*/
 };