gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libmicrohttpd] 02/03: mhd_send.c: fixed: properly handle send errors


From: gnunet
Subject: [libmicrohttpd] 02/03: mhd_send.c: fixed: properly handle send errors
Date: Sun, 13 Dec 2020 17:43:51 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit 005c7686995e68700032f178e3919c10e19047d9
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Sun Dec 13 18:35:27 2020 +0300

    mhd_send.c: fixed: properly handle send errors
    
    Fixed busy-waiting with epoll and sendmsg().
---
 src/microhttpd/mhd_send.c | 54 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c
index d19d4a57..b1c0dda6 100644
--- a/src/microhttpd/mhd_send.c
+++ b/src/microhttpd/mhd_send.c
@@ -727,19 +727,23 @@ MHD_send_on_connection_ (struct MHD_Connection 
*connection,
     ret = gnutls_record_send (connection->tls_session,
                               buffer,
                               buffer_size);
-    if ( (GNUTLS_E_AGAIN == ret) ||
-         (GNUTLS_E_INTERRUPTED == ret) )
+    if (GNUTLS_E_AGAIN == ret)
     {
 #ifdef EPOLL_SUPPORT
-      if (GNUTLS_E_AGAIN == ret)
-        connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
+      connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
 #endif
       return MHD_ERR_AGAIN_;
     }
+    if (GNUTLS_E_INTERRUPTED == ret)
+      return MHD_ERR_AGAIN_;
+    if ( (GNUTLS_E_ENCRYPTION_FAILED == ret) ||
+         (GNUTLS_E_INVALID_SESSION == ret) )
+      return MHD_ERR_CONNRESET_;
+    if (GNUTLS_E_MEMORY_ERROR == ret)
+      return MHD_ERR_NOMEM_;
     if (ret < 0)
     {
-      /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
-         disrupted); interpret as a hard error */
+      /* Treat any other error as hard error. */
       return MHD_ERR_NOTCONN_;
     }
 #ifdef EPOLL_SUPPORT
@@ -784,6 +788,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection,
         return MHD_ERR_AGAIN_;
       if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
         return MHD_ERR_CONNRESET_;
+      if (MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err))
+        return MHD_ERR_NOMEM_;
       /* Treat any other error as hard error. */
       return MHD_ERR_NOTCONN_;
     }
@@ -819,8 +825,8 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
   ssize_t ret;
   bool push_hdr;
   bool push_body;
-#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
   MHD_socket s = connection->socket_fd;
+#if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV)
   struct iovec vector[2];
 #ifdef HAVE_SENDMSG
   struct msghdr msg;
@@ -833,6 +839,12 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
 #endif /* HAVE_SENDMSG || HAVE_WRITEV */
   mhd_assert ( (NULL != body) || (0 == body_size) );
 
+  if ( (MHD_INVALID_SOCKET == s) ||
+       (MHD_CONNECTION_CLOSED == connection->state) )
+  {
+    return MHD_ERR_NOTCONN_;
+  }
+
   push_body = complete_response;
 
   if (! never_push_hdr)
@@ -936,9 +948,31 @@ MHD_send_hdr_and_body_ (struct MHD_Connection *connection,
 #elif HAVE_WRITEV
   ret = writev (s, vector, 2);
 #endif
-  if ( (-1 == ret) &&
-       (EAGAIN == errno) )
-    return MHD_ERR_AGAIN_;
+  if (0 > ret)
+  {
+    const int err = MHD_socket_get_error_ ();
+
+    if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
+    {
+#if EPOLL_SUPPORT
+      /* EAGAIN, no longer write-ready */
+      connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
+#endif /* EPOLL_SUPPORT */
+      return MHD_ERR_AGAIN_;
+    }
+    if (MHD_SCKT_ERR_IS_EINTR_ (err))
+      return MHD_ERR_AGAIN_;
+    if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
+      return MHD_ERR_CONNRESET_;
+    if (MHD_SCKT_ERR_IS_LOW_RESOURCES_ (err))
+      return MHD_ERR_NOMEM_;
+    /* Treat any other error as hard error. */
+    return MHD_ERR_NOTCONN_;
+  }
+#if EPOLL_SUPPORT
+  else if ((header_size + body_size) > (size_t) ret)
+    connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
+#endif /* EPOLL_SUPPORT */
 
   /* If there is a need to push the data from network buffers
    * call post_send_setopt(). */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]