Hi,
What is the expected semantics of calling MHD_run_from_select with a MHD
configured to use epoll in combination with an application side event loop?
I am diagnosing a problem with systemd-journal-remote which utilizes MHD
to receive journal entries from remote hosts. Currently, when
transferring a bigger journal, the remote side suddenly stops because it
seems not to receive ACKs anymore. This is because MHD_run_from_select
is left even if a connections' fd is still read-ready and
systemd-journal-remote will call epoll_wait on the corresponding fd. If
now the remote side does not send any more data epoll_wait will not be
left because of the edge triggered nature of the descriptor.
With the internal event loop, MHD has access to the state of a
connection and thus can decide if it'll have to call epoll_wait. For
external event loops however that's not true. So my answer to the above
question would be: MHD_run_from_select should never be left if there is
any more data available to be processed by the application. For edge
triggered epoll this is the only safe way of doing it I can think of.
As a proof of concept I tried a simple workaround (see attached patch)
which seems to solve the problem (only works for reads), but I am sure
that this solution is neither complete nor nice.
What's your opinion on this?
Regards,
Martin
--- libmicrohttpd-0.9.55.orig/src/microhttpd/daemon.c 2017-05-28 22:34:00.000000000 +0200
+++ libmicrohttpd-0.9.55/src/microhttpd/daemon.c 2017-09-03 15:41:00.654496718 +0200
@@ -1150,9 +1150,15 @@
if ( (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) &&
read_ready)
{
+#ifdef EPOLL_SUPPORT
+ do {
+#endif
con->read_handler (con);
ret = con->idle_handler (con);
states_info_processed = true;
+#ifdef EPOLL_SUPPORT
+ } while (con->epoll_state & MHD_EPOLL_STATE_READ_READY);
+#endif
}
/* No need to check value of 'ret' here as closed connection
* cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */