aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-03-15 19:31:42 +0000
committerChristian Grothoff <christian@grothoff.org>2016-03-15 19:31:42 +0000
commitc932ba77fde49a5c22374de96b8e56b17e746462 (patch)
treef6b0b5ad646b9089d3b7e8a95957e01cd14a0620
parentd3b17d3b19ad509e6e355677cc7fea73eb15c1b9 (diff)
downloadlibmicrohttpd-c932ba77fde49a5c22374de96b8e56b17e746462.tar.gz
libmicrohttpd-c932ba77fde49a5c22374de96b8e56b17e746462.zip
fix unnecessary and potentially problematic use of eready DLL in thread-per-connection mode
-rw-r--r--ChangeLog4
-rw-r--r--src/include/microhttpd.h2
-rw-r--r--src/microhttpd/connection.c83
-rw-r--r--src/microhttpd/daemon.c54
4 files changed, 76 insertions, 67 deletions
diff --git a/ChangeLog b/ChangeLog
index c65582d7..402463eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
1Tue Mar 15 20:29:34 CET 2016
2 Do not use eready DLL data structure unless
3 we are actually using epoll(). -DD/CG
4
1Fri Feb 5 20:43:11 CET 2016 5Fri Feb 5 20:43:11 CET 2016
2 Fixed testsuite compile warning on W32. 6 Fixed testsuite compile warning on W32.
3 Added check test for triggering poll() on 7 Added check test for triggering poll() on
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index c7f23c15..61eebb80 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -130,7 +130,7 @@ typedef intptr_t ssize_t;
130 * Current version of the library. 130 * Current version of the library.
131 * 0x01093001 = 1.9.30-1. 131 * 0x01093001 = 1.9.30-1.
132 */ 132 */
133#define MHD_VERSION 0x00094802 133#define MHD_VERSION 0x00094803
134 134
135/** 135/**
136 * MHD-internal return code for "YES". 136 * MHD-internal return code for "YES".
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index 0a9f9885..dc224588 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -2709,7 +2709,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2709 connection->state = MHD_CONNECTION_NORMAL_BODY_READY; 2709 connection->state = MHD_CONNECTION_NORMAL_BODY_READY;
2710 /* Buffering for flushable socket was already enabled*/ 2710 /* Buffering for flushable socket was already enabled*/
2711 if (MHD_NO == socket_flush_possible (connection)) 2711 if (MHD_NO == socket_flush_possible (connection))
2712 socket_start_no_buffering (connection); 2712 socket_start_no_buffering (connection);
2713 2713
2714 break; 2714 break;
2715 } 2715 }
@@ -2737,7 +2737,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2737 connection->state = MHD_CONNECTION_CHUNKED_BODY_READY; 2737 connection->state = MHD_CONNECTION_CHUNKED_BODY_READY;
2738 /* Buffering for flushable socket was already enabled */ 2738 /* Buffering for flushable socket was already enabled */
2739 if (MHD_NO == socket_flush_possible (connection)) 2739 if (MHD_NO == socket_flush_possible (connection))
2740 socket_start_no_buffering (connection); 2740 socket_start_no_buffering (connection);
2741 2741
2742 continue; 2742 continue;
2743 } 2743 }
@@ -2860,45 +2860,48 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2860 } 2860 }
2861 MHD_connection_update_event_loop_info (connection); 2861 MHD_connection_update_event_loop_info (connection);
2862#if EPOLL_SUPPORT 2862#if EPOLL_SUPPORT
2863 switch (connection->event_loop_info) 2863 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
2864 { 2864 {
2865 case MHD_EVENT_LOOP_INFO_READ: 2865 switch (connection->event_loop_info)
2866 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) && 2866 {
2867 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && 2867 case MHD_EVENT_LOOP_INFO_READ:
2868 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) 2868 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2869 { 2869 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2870 EDLL_insert (daemon->eready_head, 2870 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2871 daemon->eready_tail, 2871 {
2872 connection); 2872 EDLL_insert (daemon->eready_head,
2873 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; 2873 daemon->eready_tail,
2874 } 2874 connection);
2875 break; 2875 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2876 case MHD_EVENT_LOOP_INFO_WRITE: 2876 }
2877 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) && 2877 break;
2878 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && 2878 case MHD_EVENT_LOOP_INFO_WRITE:
2879 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) ) 2879 if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2880 { 2880 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2881 EDLL_insert (daemon->eready_head, 2881 (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2882 daemon->eready_tail, 2882 {
2883 connection); 2883 EDLL_insert (daemon->eready_head,
2884 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; 2884 daemon->eready_tail,
2885 } 2885 connection);
2886 break; 2886 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2887 case MHD_EVENT_LOOP_INFO_BLOCK: 2887 }
2888 /* we should look at this connection again in the next iteration 2888 break;
2889 of the event loop, as we're waiting on the application */ 2889 case MHD_EVENT_LOOP_INFO_BLOCK:
2890 if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) && 2890 /* we should look at this connection again in the next iteration
2891 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) ) 2891 of the event loop, as we're waiting on the application */
2892 { 2892 if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
2893 EDLL_insert (daemon->eready_head, 2893 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
2894 daemon->eready_tail, 2894 {
2895 connection); 2895 EDLL_insert (daemon->eready_head,
2896 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL; 2896 daemon->eready_tail,
2897 } 2897 connection);
2898 break; 2898 connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2899 case MHD_EVENT_LOOP_INFO_CLEANUP: 2899 }
2900 /* This connection is finished, nothing left to do */ 2900 break;
2901 break; 2901 case MHD_EVENT_LOOP_INFO_CLEANUP:
2902 /* This connection is finished, nothing left to do */
2903 break;
2904 }
2902 } 2905 }
2903 return MHD_connection_epoll_update_ (connection); 2906 return MHD_connection_epoll_update_ (connection);
2904#else 2907#else
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index bbd7b42d..14786042 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libmicrohttpd 2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2014 Daniel Pittman and Christian Grothoff 3 Copyright (C) 2007-2016 Daniel Pittman and Christian Grothoff
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
@@ -2081,30 +2081,32 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
2081 MHD_CONNECTION_NOTIFY_CLOSED); 2081 MHD_CONNECTION_NOTIFY_CLOSED);
2082 MHD_ip_limit_del (daemon, pos->addr, pos->addr_len); 2082 MHD_ip_limit_del (daemon, pos->addr, pos->addr_len);
2083#if EPOLL_SUPPORT 2083#if EPOLL_SUPPORT
2084 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) 2084 if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY))
2085 { 2085 {
2086 EDLL_remove (daemon->eready_head, 2086 if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
2087 daemon->eready_tail, 2087 {
2088 pos); 2088 EDLL_remove (daemon->eready_head,
2089 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL; 2089 daemon->eready_tail,
2090 } 2090 pos);
2091 if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && 2091 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
2092 (MHD_INVALID_SOCKET != daemon->epoll_fd) && 2092 }
2093 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) ) 2093 if ( (MHD_INVALID_SOCKET != daemon->epoll_fd) &&
2094 { 2094 (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) )
2095 /* epoll documentation suggests that closing a FD 2095 {
2096 automatically removes it from the epoll set; however, 2096 /* epoll documentation suggests that closing a FD
2097 this is not true as if we fail to do manually remove it, 2097 automatically removes it from the epoll set; however,
2098 we are still seeing an event for this fd in epoll, 2098 this is not true as if we fail to do manually remove it,
2099 causing grief (use-after-free...) --- at least on my 2099 we are still seeing an event for this fd in epoll,
2100 system. */ 2100 causing grief (use-after-free...) --- at least on my
2101 if (0 != epoll_ctl (daemon->epoll_fd, 2101 system. */
2102 EPOLL_CTL_DEL, 2102 if (0 != epoll_ctl (daemon->epoll_fd,
2103 pos->socket_fd, 2103 EPOLL_CTL_DEL,
2104 NULL)) 2104 pos->socket_fd,
2105 MHD_PANIC ("Failed to remove FD from epoll set\n"); 2105 NULL))
2106 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET; 2106 MHD_PANIC ("Failed to remove FD from epoll set\n");
2107 } 2107 pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
2108 }
2109 }
2108#endif 2110#endif
2109 if (NULL != pos->response) 2111 if (NULL != pos->response)
2110 { 2112 {
@@ -3766,7 +3768,7 @@ MHD_start_daemon_va (unsigned int flags,
3766 if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION))) 3768 if (0 == (flags & (MHD_USE_SELECT_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION)))
3767 use_pipe = 0; /* useless if we are using 'external' select */ 3769 use_pipe = 0; /* useless if we are using 'external' select */
3768 if (use_pipe) 3770 if (use_pipe)
3769 { 3771 {
3770 if (0 != MHD_pipe_ (daemon->wpipe)) 3772 if (0 != MHD_pipe_ (daemon->wpipe))
3771 { 3773 {
3772#ifdef HAVE_MESSAGES 3774#ifdef HAVE_MESSAGES