Fix remaining case of ControlConn being used after being deleted.
authorDavin McCall <davmac@davmac.org>
Mon, 23 Nov 2015 07:39:42 +0000 (07:39 +0000)
committerDavin McCall <davmac@davmac.org>
Mon, 23 Nov 2015 07:39:42 +0000 (07:39 +0000)
control.cc
control.h

index 7cf55725773f5331d0d06f8d0282d674513fe065..32447e642796c37de9bdfc62b66363407cff7d69 100644 (file)
@@ -201,7 +201,7 @@ bool ControlConn::rollbackComplete() noexcept
     return queuePacket(ackBuf, 1);
 }
 
-void ControlConn::dataReady() noexcept
+bool ControlConn::dataReady() noexcept
 {
     int fd = iob.fd;
     int buffree = 1024 - bufidx;
@@ -213,13 +213,14 @@ void ControlConn::dataReady() noexcept
         if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
             // TODO log error
             delete this;
+            return true;
         }
-        return;
+        return false;
     }
     
     if (r == 0) {
         delete this;
-        return;
+        return true;
     }
     
     bufidx += r;
@@ -243,7 +244,7 @@ void ControlConn::dataReady() noexcept
         ev_io_set(&iob, iob.fd, EV_WRITE);
     }
     
-    return;
+    return false;
 }
 
 void ControlConn::sendData() noexcept
index 79126a1242fa4e6c3b00d33783134168e808e197..845f3c7cab38b0d8edec9af917764089539152b4 100644 (file)
--- a/control.h
+++ b/control.h
@@ -67,8 +67,10 @@ class ControlConn
     // outgoing packets queued.
     void processPacket();
 
-    // Notify that data is ready to be read from the socket.
-    void dataReady() noexcept;
+    // Notify that data is ready to be read from the socket. Returns true in cases where the
+    // connection was deleted with potentially pending outgoing packets.
+    bool dataReady() noexcept;
+    
     void sendData() noexcept;
     
     public:
@@ -93,9 +95,11 @@ static void control_conn_cb(struct ev_loop * loop, ev_io * w, int revents)
 {
     ControlConn *conn = (ControlConn *) w->data;
     if (revents & EV_READ) {
-        conn->dataReady();
+        if (conn->dataReady()) {
+            // ControlConn was deleted
+            return;
+        }
     }
-    // TODO issue here: what if above deletes the connection?
     if (revents & EV_WRITE) {
         conn->sendData();
     }