]> granicus.if.org Git - libevent/commitdiff
Correctly terminate IO on an async bufferevent on bufferevent_free
authorNick Mathewson <nickm@torproject.org>
Thu, 25 Aug 2011 01:39:28 +0000 (21:39 -0400)
committerNick Mathewson <nickm@torproject.org>
Sun, 28 Aug 2011 18:39:12 +0000 (14:39 -0400)
bufferevent-internal.h
bufferevent.c
bufferevent_async.c
bufferevent_filter.c
bufferevent_openssl.c
bufferevent_sock.c

index dc4717206f671103217f0a04d0fb75fe83e0aad8..de1ff973add9e5588e9d5bf82b3c29bfc4b95c75 100644 (file)
@@ -197,7 +197,8 @@ struct bufferevent_private {
 enum bufferevent_ctrl_op {
        BEV_CTRL_SET_FD,
        BEV_CTRL_GET_FD,
-       BEV_CTRL_GET_UNDERLYING
+       BEV_CTRL_GET_UNDERLYING,
+       BEV_CTRL_CANCEL_ALL
 };
 
 /** Possible data types for a control callback */
index 9855d18322c1d93db961d72b65effa4a621f040d..93a08015f2901cbc0f65f7cc826e8b73d4beee1a 100644 (file)
@@ -59,6 +59,9 @@
 #include "evbuffer-internal.h"
 #include "util-internal.h"
 
+static void _bufferevent_cancel_all(struct bufferevent *bev);
+
+
 void
 bufferevent_suspend_read(struct bufferevent *bufev, bufferevent_suspend_flags what)
 {
@@ -674,6 +677,7 @@ bufferevent_free(struct bufferevent *bufev)
 {
        BEV_LOCK(bufev);
        bufferevent_setcb(bufev, NULL, NULL, NULL, NULL);
+       _bufferevent_cancel_all(bufev);
        _bufferevent_decref_and_unlock(bufev);
 }
 
@@ -750,6 +754,17 @@ bufferevent_getfd(struct bufferevent *bev)
        return (res<0) ? -1 : d.fd;
 }
 
+static void
+_bufferevent_cancel_all(struct bufferevent *bev)
+{
+       union bufferevent_ctrl_data d;
+       memset(&d, 0, sizeof(d));
+       BEV_LOCK(bev);
+       if (bev->be_ops->ctrl)
+               bev->be_ops->ctrl(bev, BEV_CTRL_CANCEL_ALL, &d);
+       BEV_UNLOCK(bev);
+}
+
 short
 bufferevent_get_enabled(struct bufferevent *bufev)
 {
index 9416e31f2d75e3bb9e281ad91fd6a97c9f60fba1..a3b3ab1e4aba8b7a62b0d552923aa18eb7b99265 100644 (file)
@@ -268,8 +268,8 @@ bev_async_consider_reading(struct bufferevent_async *beva)
        bufferevent_incref(bev);
        if (evbuffer_launch_read(bev->input, at_most, &beva->read_overlapped)) {
                beva->ok = 0;
-               bufferevent_decref(bev);
                _bufferevent_run_eventcb(bev, BEV_EVENT_ERROR);
+               bufferevent_decref(bev);
        } else {
                beva->read_in_progress = at_most;
                _bufferevent_decrement_read_buckets(&beva->bev, at_most);
@@ -379,8 +379,10 @@ be_async_destruct(struct bufferevent *bev)
        bev_async_del_write(bev_async);
 
        fd = _evbuffer_overlapped_get_fd(bev->input);
-       if (bev_p->options & BEV_OPT_CLOSE_ON_FREE)
+       if (bev_p->options & BEV_OPT_CLOSE_ON_FREE) {
+               /* XXXX possible double-close */
                evutil_closesocket(fd);
+       }
        /* delete this in case non-blocking connect was used */
        if (event_initialized(&bev->ev_write)) {
                event_del(&bev->ev_write);
@@ -669,8 +671,20 @@ be_async_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
                _evbuffer_overlapped_set_fd(bev->output, data->fd);
                return 0;
        }
+       case BEV_CTRL_CANCEL_ALL: {
+               struct bufferevent_async *bev_a = upcast(bev);
+               evutil_socket_t fd = _evbuffer_overlapped_get_fd(bev->input);
+               if (fd != (evutil_socket_t)INVALID_SOCKET &&
+                   (bev_a->bev.options & BEV_OPT_CLOSE_ON_FREE)) {
+                       closesocket(fd);
+               }
+               bev_a->ok = 0;
+               return 0;
+       }
        case BEV_CTRL_GET_UNDERLYING:
        default:
                return -1;
        }
 }
+
+
index 7f19eb9afd888bbae8f74abdeb6da47cd8b47a68..234204fc009e1630bd1efe964b5cc595543c9b88 100644 (file)
@@ -504,6 +504,7 @@ be_filter_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
                return 0;
        case BEV_CTRL_GET_FD:
        case BEV_CTRL_SET_FD:
+       case BEV_CTRL_CANCEL_ALL:
        default:
                return -1;
        }
index c5d242eaeb97d4d00b9288262743529b5b83b356..da50c600bcb0ee619457e5da430fa8f318c7c791 100644 (file)
@@ -1167,6 +1167,7 @@ be_openssl_ctrl(struct bufferevent *bev,
                        return -1;
                data->ptr = bev_ssl->underlying;
                return 0;
+       case BEV_CTRL_CANCEL_ALL:
        default:
                return -1;
        }
index 975b5b6cd309ceda8cd80a8a6bdb03819495113e..089aedb4d8af5877ca5026201080e16f6401fc3c 100644 (file)
@@ -685,6 +685,7 @@ be_socket_ctrl(struct bufferevent *bev, enum bufferevent_ctrl_op op,
                data->fd = event_get_fd(&bev->ev_read);
                return 0;
        case BEV_CTRL_GET_UNDERLYING:
+       case BEV_CTRL_CANCEL_ALL:
        default:
                return -1;
        }