From fc52dbac87f4937f8306759506d6a2ad15ca244c Mon Sep 17 00:00:00 2001 From: Mark Ellzey Date: Mon, 14 Nov 2011 10:24:07 -0500 Subject: 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 curl -vvvv -k -d@ 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. --- bufferevent_openssl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'bufferevent_openssl.c') 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) { -- cgit v1.2.1