From bbdcc620ef67f02fd34137ec377fb0206fb83f6d Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Fri, 5 Aug 2016 14:48:06 +0200 Subject: [PATCH] rgw: handle errors via exceptions in RGWStreamIOEngine. Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_asio_client.cc | 2 +- src/rgw/rgw_asio_client.h | 2 +- src/rgw/rgw_civetweb.cc | 35 ++++++++++++++++----- src/rgw/rgw_civetweb.h | 2 +- src/rgw/rgw_client_io.h | 52 ++++++++++++++++++++++++-------- src/rgw/rgw_client_io_decoimpl.h | 2 +- src/rgw/rgw_fcgi.cc | 12 ++++++-- src/rgw/rgw_fcgi.h | 2 +- src/rgw/rgw_lib.h | 2 +- src/rgw/rgw_loadgen.h | 2 +- 10 files changed, 84 insertions(+), 29 deletions(-) diff --git a/src/rgw/rgw_asio_client.cc b/src/rgw/rgw_asio_client.cc index 679b3078aef..42251ae1d6b 100644 --- a/src/rgw/rgw_asio_client.cc +++ b/src/rgw/rgw_asio_client.cc @@ -84,7 +84,7 @@ int RGWAsioClientIO::write_data(const char* const buf, const int len) auto bytes = boost::asio::write(socket, boost::asio::buffer(buf, len), ec); if (ec) { derr << "write_data failed with " << ec.message() << dendl; - return -ec.value(); + throw RGWStreamIOEngine::Exception(-ec.value()); } return bytes; } diff --git a/src/rgw/rgw_asio_client.h b/src/rgw/rgw_asio_client.h index 11ae0443d4f..1f0dbbcdfdb 100644 --- a/src/rgw/rgw_asio_client.h +++ b/src/rgw/rgw_asio_client.h @@ -53,7 +53,7 @@ class RGWAsioClientIO : public RGWStreamIOEngine { int complete_header() override; int send_content_length(uint64_t len) override; - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } }; diff --git a/src/rgw/rgw_civetweb.cc b/src/rgw/rgw_civetweb.cc index e9e0b0d852b..1ef15641fd2 100644 --- a/src/rgw/rgw_civetweb.cc +++ b/src/rgw/rgw_civetweb.cc @@ -14,12 +14,14 @@ int RGWCivetWeb::write_data(const char *buf, int len) { - int r = mg_write(conn, buf, len); - if (r == 0) { + const int ret = mg_write(conn, buf, len); + if (ret == 0) { /* didn't send anything, error out */ - return -EIO; + throw RGWStreamIOEngine::Exception(-EIO); + } else if (ret < 0) { + throw RGWStreamIOEngine::Exception(ret); } - return r; + return ret; } RGWCivetWeb::RGWCivetWeb(mg_connection* const conn, const int port) @@ -32,7 +34,11 @@ RGWCivetWeb::RGWCivetWeb(mg_connection* const conn, const int port) int RGWCivetWeb::read_data(char *buf, int len) { - return mg_read(conn, buf, len); + const int ret = mg_read(conn, buf, len); + if (ret < 0) { + throw RGWStreamIOEngine::Exception(ret); + } + return ret; } void RGWCivetWeb::flush() @@ -109,12 +115,25 @@ void RGWCivetWeb::init_env(CephContext *cct) } } +template +static inline std::size_t safe_mg_printf(Args&&... args) +{ + const int ret = mg_printf(std::forward(args)...); + if (ret == 0) { + /* didn't send anything, error out */ + throw RGWStreamIOEngine::Exception(-EIO); + } else if (ret < 0) { + throw RGWStreamIOEngine::Exception(ret); + } + return static_cast(ret); +} + int RGWCivetWeb::send_status(int status, const char *status_name) { mg_set_http_status(conn, status); - return mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, - status_name ? status_name : ""); + return safe_mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, + status_name ? status_name : ""); } int RGWCivetWeb::send_100_continue() @@ -161,5 +180,5 @@ int RGWCivetWeb::complete_header() int RGWCivetWeb::send_content_length(uint64_t len) { - return mg_printf(conn, "Content-Length: %" PRIu64 "\r\n", len); + return safe_mg_printf(conn, "Content-Length: %" PRIu64 "\r\n", len); } diff --git a/src/rgw/rgw_civetweb.h b/src/rgw/rgw_civetweb.h index b2bf41239e1..0072d99c306 100644 --- a/src/rgw/rgw_civetweb.h +++ b/src/rgw/rgw_civetweb.h @@ -35,7 +35,7 @@ public: void flush() override; - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } diff --git a/src/rgw/rgw_client_io.h b/src/rgw/rgw_client_io.h index 89c3123cb4d..afb8461ce91 100644 --- a/src/rgw/rgw_client_io.h +++ b/src/rgw/rgw_client_io.h @@ -4,6 +4,7 @@ #ifndef CEPH_RGW_CLIENT_IO_H #define CEPH_RGW_CLIENT_IO_H +#include #include #include #include @@ -21,7 +22,7 @@ public: virtual ~RGWClientIO() {} void init(CephContext *cct); - virtual RGWEnv& get_env() = 0; + virtual RGWEnv& get_env() noexcept = 0; virtual int complete_request() = 0; }; /* RGWClient IO */ @@ -46,6 +47,19 @@ protected: virtual int write_data(const char *buf, int len) = 0; public: + class Exception : public std::exception { + int err; + + public: + Exception(const int err) + : err(err) { + } + + int value() { + return err; + } + }; + virtual int send_status(int status, const char *status_name) = 0; virtual int send_100_continue() = 0; virtual int complete_header() = 0; @@ -106,7 +120,7 @@ public: std::string grab_aws4_sha256_hash(); - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } @@ -135,17 +149,31 @@ class RGWStreamIOLegacyWrapper : public RGWStreamIO { return *engine; } +#define EXCPT_TO_RC(code) \ + try { \ + return code; \ + } catch (RGWStreamIOEngine::Exception& e) { \ + return e.value(); \ + } + +#define EXCPT_TO_VOID(code) \ + try { \ + return code; \ + } catch (RGWStreamIOEngine::Exception& e) { \ + return; \ + } + protected: void init_env(CephContext *cct) override { - return get_decoratee().init_env(cct); + EXCPT_TO_VOID(get_decoratee().init_env(cct)); } int read_data(char* const buf, const int max) override { - return get_decoratee().read_data(buf, max); + EXCPT_TO_RC(get_decoratee().read_data(buf, max)); } int write_data(const char* const buf, const int len) override { - return get_decoratee().write_data(buf, len); + EXCPT_TO_RC(get_decoratee().write_data(buf, len)); } public: @@ -154,31 +182,31 @@ public: } int send_status(const int status, const char* const status_name) override { - return get_decoratee().send_status(status, status_name); + EXCPT_TO_RC(get_decoratee().send_status(status, status_name)); } int send_100_continue() override { - return get_decoratee().send_100_continue(); + EXCPT_TO_RC(get_decoratee().send_100_continue()); } int send_content_length(const uint64_t len) override { - return get_decoratee().send_content_length(len); + EXCPT_TO_RC(get_decoratee().send_content_length(len)); } int complete_header() override { - return get_decoratee().complete_header(); + EXCPT_TO_RC(get_decoratee().complete_header()); } void flush() override { - return get_decoratee().flush(); + EXCPT_TO_VOID(get_decoratee().flush()); } - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return get_decoratee().get_env(); } int complete_request() override { - return get_decoratee().complete_request(); + EXCPT_TO_RC(get_decoratee().complete_request()); } }; diff --git a/src/rgw/rgw_client_io_decoimpl.h b/src/rgw/rgw_client_io_decoimpl.h index 08a392cc8d5..ebb48820d03 100644 --- a/src/rgw/rgw_client_io_decoimpl.h +++ b/src/rgw/rgw_client_io_decoimpl.h @@ -79,7 +79,7 @@ public: return get_decoratee().flush(); } - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return get_decoratee().get_env(); } diff --git a/src/rgw/rgw_fcgi.cc b/src/rgw/rgw_fcgi.cc index 95f945d7c49..5b59f717b5b 100644 --- a/src/rgw/rgw_fcgi.cc +++ b/src/rgw/rgw_fcgi.cc @@ -7,12 +7,20 @@ int RGWFCGX::write_data(const char* const buf, const int len) { - return FCGX_PutStr(buf, len, fcgx->out); + const auto ret = FCGX_PutStr(buf, len, fcgx->out); + if (ret < 0) { + throw RGWStreamIOEngine::Exception(ret); + } + return ret; } int RGWFCGX::read_data(char* const buf, const int len) { - return FCGX_GetStr(buf, len, fcgx->in); + const auto ret = FCGX_GetStr(buf, len, fcgx->in); + if (ret < 0) { + throw RGWStreamIOEngine::Exception(ret); + } + return ret; } void RGWFCGX::flush() diff --git a/src/rgw/rgw_fcgi.h b/src/rgw/rgw_fcgi.h index 046dbb53e1f..4f235714e34 100644 --- a/src/rgw/rgw_fcgi.h +++ b/src/rgw/rgw_fcgi.h @@ -32,7 +32,7 @@ public: void flush(); - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } diff --git a/src/rgw/rgw_lib.h b/src/rgw/rgw_lib.h index c937d475120..c10f66915c5 100644 --- a/src/rgw/rgw_lib.h +++ b/src/rgw/rgw_lib.h @@ -77,7 +77,7 @@ namespace rgw { int complete_header(); int send_content_length(uint64_t len); - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } diff --git a/src/rgw/rgw_loadgen.h b/src/rgw/rgw_loadgen.h index 1dec5c86a50..173e493b122 100644 --- a/src/rgw/rgw_loadgen.h +++ b/src/rgw/rgw_loadgen.h @@ -55,7 +55,7 @@ public: void flush(); - RGWEnv& get_env() override { + RGWEnv& get_env() noexcept override { return env; } -- 2.47.3