summaryrefslogtreecommitdiff
path: root/bufferevent_openssl.c
diff options
context:
space:
mode:
authorMark Ellzey <mark.thomas@mandiant.com>2011-11-14 10:24:07 -0500
committerNick Mathewson <nickm@torproject.org>2011-11-14 11:52:51 -0500
commitfc52dbac87f4937f8306759506d6a2ad15ca244c (patch)
tree28c96d045b8571010409f62a41c2a9976728e756 /bufferevent_openssl.c
parenta3f320e83d97dbd58afa883d8a1e2cf3cdc1ac39 (diff)
downloadlibevent-fc52dbac87f4937f8306759506d6a2ad15ca244c.tar.gz
Avoid potential SSL read spinlocks
OpenSSL bufferevents with deferred callbacks enabled under high load will spinlock in the function consider_reading(). This loop continues until all data has been read. Because of this condition; openssl bufferevents will never return back into event_base_loop() until SSL_read has determined data is no longer ready. As of yet I have not found a reason why this while loop exists, so this patch just swaps out while for if. If needed I can write same code which would trigger this effect; optionally libevhtp has a test.c program which can be run with the following flags: ./test -s <keyfile.pem> curl -vvvv -k -d@<HUGE_ASS_FILE> https://127.0.0.1:8081/ The return data will include the number of times the readcb got data and the length of that read. Without this patch, you are likely to see a small amount of "bytes read....", otherwise the "bytes read..." return data should show much more reasonable numbers.
Diffstat (limited to 'bufferevent_openssl.c')
-rw-r--r--bufferevent_openssl.c4
1 files changed, 1 insertions, 3 deletions
diff --git a/bufferevent_openssl.c b/bufferevent_openssl.c
index 86a8619b..3843b314 100644
--- a/bufferevent_openssl.c
+++ b/bufferevent_openssl.c
@@ -722,15 +722,13 @@ consider_reading(struct bufferevent_openssl *bev_ssl)
}
if (bev_ssl->write_blocked_on_read)
return;
- while ((bev_ssl->bev.bev.enabled & EV_READ) &&
+ if ((bev_ssl->bev.bev.enabled & EV_READ) &&
(! bev_ssl->bev.read_suspended) &&
(! wm->high || evbuffer_get_length(input) < wm->high)) {
int n_to_read =
wm->high ? wm->high - evbuffer_get_length(input)
: READ_DEFAULT;
r = do_read(bev_ssl, n_to_read);
- if (r <= 0)
- break;
}
if (!bev_ssl->underlying) {