summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorteor <teor@torproject.org>2019-11-25 12:36:59 +1000
committerteor <teor@torproject.org>2019-11-25 12:36:59 +1000
commit055f5d4d1b2c8ea5a85691f7110e82a9c468b6dd (patch)
treebeefb267f60a2800e2499cc2a7e354408ef81f9c /src/core
parentc17ab20ac0d3efb1b9c46fa12685db5b09015481 (diff)
parent501b5174d84a121fe5932433e54b2929a5c2876d (diff)
downloadtor-055f5d4d1b2c8ea5a85691f7110e82a9c468b6dd.tar.gz
tor-055f5d4d1b2c8ea5a85691f7110e82a9c468b6dd.zip
Merge branch 'maint-0.3.5' into maint-0.4.0
Diffstat (limited to 'src/core')
-rw-r--r--src/core/mainloop/connection.c18
-rw-r--r--src/core/mainloop/mainloop.c10
-rw-r--r--src/core/mainloop/periodic.c5
3 files changed, 27 insertions, 6 deletions
diff --git a/src/core/mainloop/connection.c b/src/core/mainloop/connection.c
index 73b8ef4da5..21d7bd6d0d 100644
--- a/src/core/mainloop/connection.c
+++ b/src/core/mainloop/connection.c
@@ -897,13 +897,19 @@ connection_mark_for_close_(connection_t *conn, int line, const char *file)
}
/** Mark <b>conn</b> to be closed next time we loop through
- * conn_close_if_marked() in main.c; the _internal version bypasses the
- * CONN_TYPE_OR checks; this should be called when you either are sure that
- * if this is an or_connection_t the controlling channel has been notified
- * (e.g. with connection_or_notify_error()), or you actually are the
+ * conn_close_if_marked() in main.c.
+ *
+ * This _internal version bypasses the CONN_TYPE_OR checks; this should be
+ * called when you either are sure that if this is an or_connection_t the
+ * controlling channel has been notified (e.g. with
+ * connection_or_notify_error()), or you actually are the
* connection_or_close_for_error() or connection_or_close_normally() function.
- * For all other cases, use connection_mark_and_flush() instead, which
- * checks for or_connection_t properly, instead. See below.
+ * For all other cases, use connection_mark_and_flush() which checks for
+ * or_connection_t properly, instead. See below.
+ *
+ * We want to keep this function simple and quick, since it can be called from
+ * quite deep in the call chain, and hence it should avoid having side-effects
+ * that interfere with its callers view of the connection.
*/
MOCK_IMPL(void,
connection_mark_for_close_internal_, (connection_t *conn,
diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c
index 193df61d01..e8de578b67 100644
--- a/src/core/mainloop/mainloop.c
+++ b/src/core/mainloop/mainloop.c
@@ -877,6 +877,16 @@ conn_read_callback(evutil_socket_t fd, short event, void *_conn)
/* assert_connection_ok(conn, time(NULL)); */
+ /* Handle marked for close connections early */
+ if (conn->marked_for_close && connection_is_reading(conn)) {
+ /* Libevent says we can read, but we are marked for close so we will never
+ * try to read again. We will try to close the connection below inside of
+ * close_closeable_connections(), but let's make sure not to cause Libevent
+ * to spin on conn_read_callback() while we wait for the socket to let us
+ * flush to it.*/
+ connection_stop_reading(conn);
+ }
+
if (connection_handle_read(conn) < 0) {
if (!conn->marked_for_close) {
#ifndef _WIN32
diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c
index c0363b15ea..5c01213d17 100644
--- a/src/core/mainloop/periodic.c
+++ b/src/core/mainloop/periodic.c
@@ -133,6 +133,11 @@ periodic_event_destroy(periodic_event_item_t *event)
{
if (!event)
return;
+
+ /* First disable the event so we first cancel the event and set its enabled
+ * flag properly. */
+ periodic_event_disable(event);
+
mainloop_event_free(event->ev);
event->last_action_time = 0;
}