summaryrefslogtreecommitdiffhomepage
path: root/plugins/fcgi/socket.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-05-21 18:00:25 +0200
committerRoland Reichwein <mail@reichwein.it>2020-05-21 18:00:25 +0200
commit4b34a4d950f762b5d020d5ac4d3354836833039c (patch)
tree6753cadbc2d4d956d18b045207278562bc9a56ee /plugins/fcgi/socket.cpp
parent72a0f20c07ecf321a4d15f5afe8938eb2b509668 (diff)
FCGI: Fix connection handling on broken pipe: Reopen new socket
Diffstat (limited to 'plugins/fcgi/socket.cpp')
-rw-r--r--plugins/fcgi/socket.cpp49
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) {