libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit c932ba77fde49a5c22374de96b8e56b17e746462
parent d3b17d3b19ad509e6e355677cc7fea73eb15c1b9
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 15 Mar 2016 19:31:42 +0000

fix unnecessary and potentially problematic use of eready DLL in thread-per-connection mode

Diffstat:
MChangeLog | 4++++
Msrc/include/microhttpd.h | 2+-
Msrc/microhttpd/connection.c | 83+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/microhttpd/daemon.c | 54++++++++++++++++++++++++++++--------------------------
4 files changed, 76 insertions(+), 67 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,7 @@ +Tue Mar 15 20:29:34 CET 2016 + Do not use eready DLL data structure unless + we are actually using epoll(). -DD/CG + Fri Feb 5 20:43:11 CET 2016 Fixed testsuite compile warning on W32. Added check test for triggering poll() on diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -130,7 +130,7 @@ typedef intptr_t ssize_t; * Current version of the library. * 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00094802 +#define MHD_VERSION 0x00094803 /** * MHD-internal return code for "YES". diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c @@ -2709,7 +2709,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) connection->state = MHD_CONNECTION_NORMAL_BODY_READY; /* Buffering for flushable socket was already enabled*/ if (MHD_NO == socket_flush_possible (connection)) - socket_start_no_buffering (connection); + socket_start_no_buffering (connection); break; } @@ -2737,7 +2737,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) connection->state = MHD_CONNECTION_CHUNKED_BODY_READY; /* Buffering for flushable socket was already enabled */ if (MHD_NO == socket_flush_possible (connection)) - socket_start_no_buffering (connection); + socket_start_no_buffering (connection); continue; } @@ -2860,45 +2860,48 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) } MHD_connection_update_event_loop_info (connection); #if EPOLL_SUPPORT - switch (connection->event_loop_info) + if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) { - case MHD_EVENT_LOOP_INFO_READ: - if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && - (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && - (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) - { - EDLL_insert (daemon->eready_head, - daemon->eready_tail, - connection); - connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; - } - break; - case MHD_EVENT_LOOP_INFO_WRITE: - if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) && - (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && - (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) - { - EDLL_insert (daemon->eready_head, - daemon->eready_tail, - connection); - connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; - } - break; - case MHD_EVENT_LOOP_INFO_BLOCK: - /* we should look at this connection again in the next iteration - of the event loop, as we're waiting on the application */ - if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) && - (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) ) - { - EDLL_insert (daemon->eready_head, - daemon->eready_tail, - connection); - connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; - } - break; - case MHD_EVENT_LOOP_INFO_CLEANUP: - /* This connection is finished, nothing left to do */ - break; + switch (connection->event_loop_info) + { + case MHD_EVENT_LOOP_INFO_READ: + if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && + (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && + (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) + { + EDLL_insert (daemon->eready_head, + daemon->eready_tail, + connection); + connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; + } + break; + case MHD_EVENT_LOOP_INFO_WRITE: + if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) && + (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && + (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) + { + EDLL_insert (daemon->eready_head, + daemon->eready_tail, + connection); + connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; + } + break; + case MHD_EVENT_LOOP_INFO_BLOCK: + /* we should look at this connection again in the next iteration + of the event loop, as we're waiting on the application */ + if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) && + (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) ) + { + EDLL_insert (daemon->eready_head, + daemon->eready_tail, + connection); + connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; + } + break; + case MHD_EVENT_LOOP_INFO_CLEANUP: + /* This connection is finished, nothing left to do */ + break; + } } return MHD_connection_epoll_update_ (connection); #else diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -1,6 +1,6 @@ /* This file is part of libmicrohttpd - Copyright (C) 2007-2014 Daniel Pittman and Christian Grothoff + Copyright (C) 2007-2016 Daniel Pittman and Christian Grothoff This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -2081,30 +2081,32 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) MHD_CONNECTION_NOTIFY_CLOSED); MHD_ip_limit_del (daemon, pos->addr, pos->addr_len); #if EPOLL_SUPPORT - if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) - { - EDLL_remove (daemon->eready_head, - daemon->eready_tail, - pos); - pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL; - } - if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && - (MHD_INVALID_SOCKET != daemon->epoll_fd) && - (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) ) - { - /* epoll documentation suggests that closing a FD - automatically removes it from the epoll set; however, - this is not true as if we fail to do manually remove it, - we are still seeing an event for this fd in epoll, - causing grief (use-after-free...) --- at least on my - system. */ - if (0 != epoll_ctl (daemon->epoll_fd, - EPOLL_CTL_DEL, - pos->socket_fd, - NULL)) - MHD_PANIC ("Failed to remove FD from epoll set\n"); - pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET; - } + if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) + { + if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) + { + EDLL_remove (daemon->eready_head, + daemon->eready_tail, + pos); + pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL; + } + if ( (MHD_INVALID_SOCKET != daemon->epoll_fd) && + (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) ) + { + /* epoll documentation suggests that closing a FD + automatically removes it from the epoll set; however, + this is not true as if we fail to do manually remove it, + we are still seeing an event for this fd in epoll, + causing grief (use-after-free...) --- at least on my + system. */ + if (0 != epoll_ctl (daemon->epoll_fd, + EPOLL_CTL_DEL, + pos->socket_fd, + NULL)) + MHD_PANIC ("Failed to remove FD from epoll set\n"); + pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET; + } + } #endif if (NULL != pos->response) { @@ -3766,7 +3768,7 @@ MHD_start_daemon_va (unsigned int flags, if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION))) use_pipe = 0; /* useless if we are using 'external' select */ if (use_pipe) - { + { if (0 != MHD_pipe_ (daemon->wpipe)) { #ifdef HAVE_MESSAGES