From 1213d3dd8b477faa80b4828e16edc467d1007f20 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 20 Oct 2010 13:41:02 -0400 Subject: [PATCH] Fix a 100%-CPU bug where an SSL connection would sometimes never stop trying to write If an SSL connection becamse disabled or suspended before became open, it could (under the right circumstances) wind up without ever getting its write callback disabled. The most correct fix is probably more subtle, and involves checking all caseswhen a write callback is enabled or disabled. This fix is more blunt, and explicitly checks whether the callback should have been disabled at the end of the callback to prevent infinite looping. Diagnosed with help from Sebastian Hahn --- bufferevent_openssl.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c index 529c1a87..e48251c3 100644 --- a/bufferevent_openssl.c +++ b/bufferevent_openssl.c @@ -732,6 +732,14 @@ consider_reading(struct bufferevent_openssl *bev_ssl) if (r <= 0) break; } + + if (!bev_ssl->underlying) { + /* Should be redundant, but let's avoid busy-looping */ + if (bev_ssl->bev.read_suspended || + !(bev_ssl->bev.bev.enabled & EV_READ)) { + event_del(&bev_ssl->bev.bev.ev_read); + } + } } static void @@ -767,8 +775,15 @@ consider_writing(struct bufferevent_openssl *bev_ssl) break; } - if (!bev_ssl->underlying && !evbuffer_get_length(output)) - event_del(&bev_ssl->bev.bev.ev_write); + if (!bev_ssl->underlying) { + if (evbuffer_get_length(output) == 0) { + event_del(&bev_ssl->bev.bev.ev_write); + } else if (bev_ssl->bev.write_suspended || + !(bev_ssl->bev.bev.enabled & EV_WRITE)) { + /* Should be redundant, but let's avoid busy-looping */ + event_del(&bev_ssl->bev.bev.ev_write); + } + } } static void