On Fri, 5 May 2017 21:09:21 +0300
Evgeny Grin <[email protected]> wrote:

> Hi José,
> 
> Shouldn't be any change.
> Could you provide minimal example?
> 

Hi Evgeny,

I was busy yesterday but I now have an example showing the regression.
I send it attached. I tested it against current master version
(917342b3fb0547523f2b4c6e607bb2ffd9cacdfd) and against version 0.9.49
(aka libmicrohttpd.so.12.37.0). The former doesn't work, the later
does.

How to test:

  gcc -o tmhd tmhd.c -lmicrohttpd && ./tmhd
  LD_PRELOAD=somewhere/libmicrohttpd.so.12.37.0  ./tmhd

And:

  curl -i localhost:7878/index

What is bad? No reply is sent in the bad case, "curl" command doesn't
return. In the good case, it returns immediately as:


  > curl -i localhost:7878/index
  HTTP/1.1 403 Forbidden
  Connection: Keep-Alive
  Content-Length: 0
  Date: Wed, 10 May 2017 07:29:11 GMT

To circumvent it, you can replace #if 0 with #if 1, leading to call
MHD_run one more time. So there is a workaround.

My feeling is that this is a typical use case and it should work with
only one call to MHD_run. I also think that providing a way to resume a
connection and sending the pending data without having to call MHD_run
would help (but is not required).

Best regards
José

#define _GNU_SOURCE

#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <poll.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>

#include <microhttpd.h>

static struct MHD_Connection *con = NULL;

static int access_handler(
		void *cls,
		struct MHD_Connection *connection,
		const char *url,
		const char *methodstr,
		const char *version,
		const char *upload_data,
		size_t *upload_data_size,
		void **recordreq)
{
	con = connection;
	MHD_suspend_connection (connection);
	return MHD_YES;
}

int main(int ac, char **av)
{
	int rc;
	struct MHD_Daemon *httpd;
	const union MHD_DaemonInfo *info;
	struct pollfd pfd;
	struct MHD_Response *response = MHD_create_response_from_buffer(0, "forbidden", MHD_RESPMEM_PERSISTENT);

	httpd = MHD_start_daemon(
		MHD_USE_EPOLL_LINUX_ONLY | MHD_USE_TCP_FASTOPEN | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME,
		7878,			/* port */
		NULL, NULL,
		access_handler, NULL,	/* Http Request Call back + extra attribute */
		MHD_OPTION_END);	/* options-end */

	if (httpd == NULL) {
		fprintf(stderr, "can't start");
		return 1;
	}

	info = MHD_get_daemon_info(httpd, MHD_DAEMON_INFO_EPOLL_FD_LINUX_ONLY);
	if (info == NULL) {
		MHD_stop_daemon(httpd);
		fprintf(stderr, "can't get poll info");
		return 1;
	}

	pfd.fd = info->listen_fd;
	pfd.events = POLLIN;
	for (;;) {
		poll(&pfd, 1, -1);
		MHD_run(httpd);
		if (con) {
			MHD_resume_connection(con);
			MHD_queue_response(con, MHD_HTTP_FORBIDDEN, response);
			con = NULL;
			MHD_run(httpd);
#if 0 /* change to 1 to get the correct behaviour */
			MHD_run(httpd);
#endif
		}
	}

	return 0;
}



Reply via email to