diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-05-21 18:00:25 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-05-21 18:00:25 +0200 |
commit | 4b34a4d950f762b5d020d5ac4d3354836833039c (patch) | |
tree | 6753cadbc2d4d956d18b045207278562bc9a56ee /plugins/fcgi/socket.cpp | |
parent | 72a0f20c07ecf321a4d15f5afe8938eb2b509668 (diff) |
FCGI: Fix connection handling on broken pipe: Reopen new socket
Diffstat (limited to 'plugins/fcgi/socket.cpp')
-rw-r--r-- | plugins/fcgi/socket.cpp | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/plugins/fcgi/socket.cpp b/plugins/fcgi/socket.cpp index badcec6..82bb06b 100644 --- a/plugins/fcgi/socket.cpp +++ b/plugins/fcgi/socket.cpp @@ -81,11 +81,44 @@ void TCPSocket::open() bool TCPSocket::is_open() { - return m_socket.is_open(); + if (m_socket.is_open()) { + std::vector<char> inbuf; + + int error; + socklen_t len = sizeof (error); + int retval {getsockopt(m_socket.native_handle(), SOL_SOCKET, SO_ERROR, &error, &len)}; + + if (retval) { + std::cerr << "FCGI Error: getsockopt() error in is_open(): " << strerror(errno) << std::endl; + try { + // for graceful shutdown, according to + // https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/basic_stream_socket/close/overload1.html + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_socket.close(); // correct state + } catch (...) { + std::cerr << "Error on shutdown/close" << std::endl; + } + return false; + } + + if (error != 0) { + try { + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); + m_socket.close(); // correct state + } catch (...) { + std::cerr << "Error on shutdown/close" << std::endl; + } + return false; + } + + return true; + } else + return false; } void TCPSocket::close() { + m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both); m_socket.close(); } @@ -96,6 +129,8 @@ size_t TCPSocket::write(const std::vector<char>& data) } catch (const boost::system::system_error& ex) { if (ex.code() == boost::asio::error::eof) { throw fcgi_eof_error("EOF on write"); + } else if (ex.code() == boost::asio::error::broken_pipe) { + throw fcgi_broken_pipe_error("Application server connection broken"); } else throw std::runtime_error("FCGI Error: Unknown boost asio exception on write: "s + ex.what()); } catch (const std::exception& ex) { @@ -108,12 +143,12 @@ size_t TCPSocket::read(std::vector<char>& data) try { size_t result{0}; - while (m_socket.available()) { + do { std::vector<char> inbuf_part(1024); size_t got { m_socket.read_some(boost::asio::buffer(inbuf_part))}; data.insert(data.end(), inbuf_part.begin(), inbuf_part.begin() + got); result += got; - } + } while (m_socket.available()); return result; @@ -165,6 +200,8 @@ size_t FileSocket::write(const std::vector<char>& data) } catch (const boost::system::system_error& ex) { if (ex.code() == boost::asio::error::eof) { throw fcgi_eof_error("EOF on write"); + } else if (ex.code() == boost::asio::error::broken_pipe) { + throw fcgi_broken_pipe_error("Application server connection broken"); } else throw std::runtime_error("FCGI Error: Unknown boost asio exception on write: "s + ex.what()); } catch (const std::exception& ex) { @@ -176,13 +213,13 @@ size_t FileSocket::read(std::vector<char>& data) { try { size_t result{0}; - - while (m_socket.available()) { + + do { std::vector<char> inbuf_part(1024); size_t got { m_socket.read_some(boost::asio::buffer(inbuf_part))}; data.insert(data.end(), inbuf_part.begin(), inbuf_part.begin() + got); result += got; - } + } while (m_socket.available()); return result; } catch (const boost::system::system_error& ex) { |