fix some segfaults with event
authorTero Marttila <terom@fixme.fi>
Mon, 31 Aug 2009 22:10:46 +0300
changeset 42 0ff56f7216ee
parent 41 02f7c0539843
child 47 b45a6648931c
fix some segfaults with event
qmsk/net/lib/event2/event.pyx
test/lib_event.py
--- 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, <void *>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)
-
--- 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()