libmicrohttpd

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

commit 086ba366b757984dc68577aaa6dac7b2d5a7c2ac
parent 741ca4907942d10defcc6133286e1766665d18c1
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu,  9 Apr 2015 07:03:26 +0000

Hi all,

I was trying to use MHD_suspend_connection() and MHD_resume_connection() to implement long polling on a request. I am using options MHD_USE_SELECT_INTERNALLY and MHD_USE_POLL options. I noticed the server thread went to 100% CPU after the first MHD_resume_connection() call. Looking at the code in MHD_poll_all() I can see that the file descriptor from daemon->wpipe[0] gets inserted into the list of file descriptors to poll but this file descriptor is never read so every time this function is called it returns immediately. The code works fine if I drop to using just MHD_USE_SELECT_INTERNALLY.

The patch below fixes the problem.

Regards,
Denis


Diffstat:
MAUTHORS | 1+
MChangeLog | 5+++++
Msrc/microhttpd/daemon.c | 9+++++++++
3 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/AUTHORS b/AUTHORS @@ -52,6 +52,7 @@ Sree Harsha Totakura <sreeharsha@totakura.in> Hani Benhabiles <kroosec@gmail.com> Guy Martin <gmsoft@tuxicoman.be> Robert Groenenberg <robert.groenenberg@broadforward.com> +Denis Dowling <denis.dowling@hsd.com.au> Documentation contributions also came from: diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +Thu Apr 9 09:01:15 CEST 2015 + Fixing issue with undrained signal pipe when using + MHD_USE_SELECT_INTERNALLY and MHD_USE_POLL in combination + with MHD_resume_connection(), causing 100% CPU usage. -DD + Tue Apr 7 00:12:36 CEST 2015 Releasing libmicrohttpd 0.9.40. -CG diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -2317,6 +2317,8 @@ MHD_poll_all (struct MHD_Daemon *daemon, int timeout; unsigned int poll_server; int poll_listen; + int poll_pipe; + char tmp; memset (p, 0, sizeof (p)); poll_server = 0; @@ -2331,11 +2333,13 @@ MHD_poll_all (struct MHD_Daemon *daemon, poll_listen = (int) poll_server; poll_server++; } + poll_pipe = -1; if (MHD_INVALID_PIPE_ != daemon->wpipe[0]) { p[poll_server].fd = daemon->wpipe[0]; p[poll_server].events = POLLIN; p[poll_server].revents = 0; + poll_pipe = (int) poll_server; poll_server++; } if (may_block == MHD_NO) @@ -2433,6 +2437,11 @@ MHD_poll_all (struct MHD_Daemon *daemon, if ( (-1 != poll_listen) && (0 != (p[poll_listen].revents & POLLIN)) ) (void) MHD_accept_connection (daemon); + + /* handle pipe FD */ + if ( (-1 != poll_pipe) && + (0 != (p[poll_pipe].revents & POLLIN)) ) + (void) MHD_pipe_read_ (daemon->wpipe[0], &tmp, sizeof (tmp)); } return MHD_YES; }