diff options
Diffstat (limited to 'plugins/fcgi')
| -rw-r--r-- | plugins/fcgi/fcgi.cpp | 10 | ||||
| -rw-r--r-- | plugins/fcgi/socket.cpp | 49 | ||||
| -rw-r--r-- | plugins/fcgi/socket.h | 6 | 
3 files changed, 57 insertions, 8 deletions
diff --git a/plugins/fcgi/fcgi.cpp b/plugins/fcgi/fcgi.cpp index 5a7ce65..7748845 100644 --- a/plugins/fcgi/fcgi.cpp +++ b/plugins/fcgi/fcgi.cpp @@ -357,7 +357,7 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context)   std::lock_guard<std::mutex> socket_lock{socket->getMutex()};   if (!socket->is_open()) { -  //std::cout << "FCGI: Opening new socket" << std::endl; +  std::cout << "FCGI: Opening new socket to " << app_addr << std::endl;    socket->open();    opening = true; @@ -402,7 +402,12 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context)     std::cerr << "Warning: Not all bytes written" << std::endl;   } catch (const fcgi_eof_error&) {     std::cerr << "FCGI Error: EOF on write" << std::endl; // seems to be ok here +   m_sockets.erase(app_addr); // force new socket next time     return HttpStatus("500", "FCGI connection: EOF on write", context.SetResponseHeader); + } catch (const fcgi_broken_pipe_error&) { +   std::cerr << "FCGI Error: Broken pipe on write" << std::endl; // seems to be ok here +   m_sockets.erase(app_addr); // force new socket next time +   return HttpStatus("500", "FCGI connection: Broken pipe on write", context.SetResponseHeader);   }  #if 0 @@ -418,7 +423,8 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context)    try {     socket->read(inbuf);    } catch (const fcgi_eof_error&) { -   std::cerr << "FCGI Warning: Early EOF" << std::endl; // seems to be ok here +   std::cerr << "FCGI Warning: Early EOF from application server. Break." << std::endl; // seems to be ok here +   m_sockets.erase(app_addr); // force new socket next time     ended = true;     //return HttpStatus("500", "FCGI connection: EOF on read", context.SetResponseHeader);    } 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) { diff --git a/plugins/fcgi/socket.h b/plugins/fcgi/socket.h index 8fb5610..272b844 100644 --- a/plugins/fcgi/socket.h +++ b/plugins/fcgi/socket.h @@ -15,6 +15,12 @@ public:   fcgi_eof_error(const std::string& what_arg): std::runtime_error(what_arg) {}  }; +class fcgi_broken_pipe_error: public std::runtime_error +{ +public: + fcgi_broken_pipe_error(const std::string& what_arg): std::runtime_error(what_arg) {} +}; +  class Socket  {   std::mutex m_mutex; // guard socket use in different threads  | 
