diff options
author | Mark Ellzey <mark.thomas@mandiant.com> | 2011-11-14 10:24:07 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2011-11-14 11:52:51 -0500 |
commit | fc52dbac87f4937f8306759506d6a2ad15ca244c (patch) | |
tree | 28c96d045b8571010409f62a41c2a9976728e756 /bufferevent_openssl.c | |
parent | a3f320e83d97dbd58afa883d8a1e2cf3cdc1ac39 (diff) | |
download | libevent-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.c | 4 |
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) { |