# HG changeset patch # User Tero Marttila # Date 1251745846 -10800 # Node ID 0ff56f7216ee80c1dd12de3a51f02d83e66a6372 # Parent 02f7c0539843239298ec8c3457cd16de7edb7e24 fix some segfaults with event diff -r 02f7c0539843 -r 0ff56f7216ee qmsk/net/lib/event2/event.pyx --- a/qmsk/net/lib/event2/event.pyx Mon Aug 31 21:36:15 2009 +0300 +++ b/qmsk/net/lib/event2/event.pyx Mon Aug 31 22:10:46 2009 +0300 @@ -39,7 +39,11 @@ cdef class event : - def __init__ (self, event_base base, lib.evutil_socket_t fd, short events) : + def __init__ (self, event_base base not None, lib.evutil_socket_t fd, short events) : + + # libevent seems to segfault otherwise... + if events & (lib.EV_READ | lib.EV_WRITE) and fd < 0 : + raise ValueError(fd) # construct event using our internal callback, with self as the arg self.ev = lib.event_new(base.ev_base, fd, events, ev_callback, self) @@ -48,7 +52,7 @@ raise Exception("event_new") - def assign (self, event_base base, lib.evutil_socket_t fd, short events) : + def assign (self, event_base base not None, lib.evutil_socket_t fd, short events) : """ Re-assign our event parameters to the given ones. @@ -98,10 +102,13 @@ lib.event_active(self.ev, fd, mask) - def pending (self, short mask) : + def pending (self, short mask = 0xffff) : """ Returns a bool indicating if this event is pending (that is, has been .add()'d). + For convenience, this defaults to testing all possible flags, and so will return true if any events are + pending. + XXX: support returning timeout value? """ @@ -138,6 +145,7 @@ XXX: what happens if event_base's __dealloc__ is triggered, but there are still event objects alive? """ + + if self.ev != NULL : + lib.event_free(self.ev) - lib.event_free(self.ev) - diff -r 02f7c0539843 -r 0ff56f7216ee test/lib_event.py --- a/test/lib_event.py Mon Aug 31 21:36:15 2009 +0300 +++ b/test/lib_event.py Mon Aug 31 22:10:46 2009 +0300 @@ -42,7 +42,91 @@ self.assertFalse(self.ev_base.loop(nonblock=True)) - +class TestEvent (unittest.TestCase) : + """ + Simple event bits. + """ + + def setUp (self) : + self.ev_base = event_base() + self.ev = event(self.ev_base, 0, EV_READ) + + def test_add (self) : + """ + .add() works. + """ + + self.assertFalse(self.ev.pending(EV_READ)) + + self.ev.add() + + self.assertTrue(self.ev.pending(EV_READ)) + + def test_add_timeout (self) : + """ + .add() with timeout works + """ + + self.ev.add(1.1) + self.assertTrue(self.ev.pending()) + + def test_add_del (self) : + """ + .add() and then .delete() works + """ + + self.assertFalse(self.ev.pending()) + + # add it in + self.ev.add() + + self.assertTrue(self.ev.pending()) + + # ensure that the ev_base is indeed not empty + self.assertTrue(self.ev_base.loop(nonblock=True)) + + + # remove it again + self.ev.delete() + + self.assertFalse(self.ev.pending()) + + # ensure that the ev_base is indeed empty + self.assertFalse(self.ev_base.loop(nonblock=True)) + + def test_invalid_base (self) : + """ + Building an event with invalid base (None) fails + """ + + # XXX: this doesn't actually seem to check against None, just the type..? + self.assertRaises(TypeError, event, None, 0, EV_READ) + + def test_illegal_fd (self) : + """ + Building an event with an illegal fd (-1) fails + """ + + self.assertRaises(ValueError, event, self.ev_base, -1, EV_READ) + + def test_invalid_fd (self) : + """ + Building an event with an invalid fd (>= 0) fails when calling .add() + """ + + ev = event(self.ev_base, 666, EV_READ) + + # XXX: be more specific about Exception + self.assertRaises(Exception, ev.add) + + def test_invalid_mask_zero (self) : + """ + Building an event with an invalid mask (0)... XXX: works? + """ + + ev = event(self.ev_base, 0, 0) + ev.add() + class TestEventPipe (unittest.TestCase) : """ Test basic event stuff using a pipe. @@ -103,6 +187,6 @@ # test self.assertEquals(ev.ev_out, None) - + if __name__ == '__main__' : unittest.main()