libmicrohttpd

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

commit 4b795e9fc603ccddeea2599c6919f80029837136
parent a22746fc8514f7c947b8433a0ee7d35c735a7bd6
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Thu, 10 Nov 2016 21:47:33 +0300

Added MHD_USE_AUTO and MHD_USE_AUTO_INTERNAL_THREAD to simplify using of MHD by multi-platform applications

Diffstat:
MChangeLog | 7+++++++
Mdoc/examples/hellobrowser.c | 2+-
Mdoc/examples/simplepost.c | 2+-
Msrc/examples/chunked_example.c | 5+++--
Msrc/examples/demo.c | 6+-----
Msrc/examples/demo_https.c | 6+-----
Msrc/examples/minimal_example.c | 5+++--
Msrc/examples/minimal_example_comet.c | 2+-
Msrc/examples/upgrade_example.c | 2+-
Msrc/include/microhttpd.h | 25+++++++++++++++++++++++--
Msrc/microhttpd/daemon.c | 36+++++++++++++++++++++++++++++++++++-
Msrc/microhttpd/test_upgrade.c | 32++++++++++++++++++++++++++++++++
Msrc/testcurl/perf_get.c | 12+++++++++---
Msrc/testcurl/perf_get_concurrent.c | 12+++++++++---
14 files changed, 127 insertions(+), 27 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,10 @@ +Thu Nov 10 21:50:35 MSK 2016 + Added rejection in MHD_start_daemon() of invalid combinations + of daemon flags. + Added MHD_USE_AUTO and MHD_USE_AUTO_INTERNAL_THREAD for + automatic selection of polling function depending on + platform capabilities and requested mode. -EG + Thu Nov 10 17:49:56 MSK 2016 Ported "upgrade" tests to W32 and other platforms, used "gnutls-cli" instead of "openssl" in tests, minor bugs diff --git a/doc/examples/hellobrowser.c b/doc/examples/hellobrowser.c @@ -39,7 +39,7 @@ main () { struct MHD_Daemon *daemon; - daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + daemon = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_END); if (NULL == daemon) return 1; diff --git a/doc/examples/simplepost.c b/doc/examples/simplepost.c @@ -183,7 +183,7 @@ main () { struct MHD_Daemon *daemon; - daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, + daemon = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, PORT, NULL, NULL, &answer_to_connection, NULL, MHD_OPTION_NOTIFY_COMPLETED, request_completed, NULL, MHD_OPTION_END); diff --git a/src/examples/chunked_example.c b/src/examples/chunked_example.c @@ -78,8 +78,9 @@ main (int argc, char *const *argv) printf ("%s PORT\n", argv[0]); return 1; } - d = MHD_start_daemon (// MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, - MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + d = MHD_start_daemon (// MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + // MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, atoi (argv[1]), diff --git a/src/examples/demo.c b/src/examples/demo.c @@ -883,11 +883,7 @@ main (int argc, char *const *argv) MHD_RESPMEM_PERSISTENT); mark_as_html (internal_error_response); update_directory (); - d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG -#ifdef EPOLL_SUPPORT - | MHD_USE_EPOLL -#endif - , + d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, port, NULL, NULL, &generate_page, NULL, diff --git a/src/examples/demo_https.c b/src/examples/demo_https.c @@ -932,11 +932,7 @@ main (int argc, char *const *argv) MHD_RESPMEM_PERSISTENT); mark_as_html (internal_error_response); update_directory (); - d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_TLS -#ifdef EPOLL_SUPPORT - | MHD_USE_EPOLL -#endif - , + d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_TLS, port, NULL, NULL, &generate_page, NULL, diff --git a/src/examples/minimal_example.c b/src/examples/minimal_example.c @@ -67,8 +67,9 @@ main (int argc, char *const *argv) printf ("%s PORT\n", argv[0]); return 1; } - d = MHD_start_daemon (// MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, - MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + d = MHD_start_daemon (// MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + // MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, atoi (argv[1]), diff --git a/src/examples/minimal_example_comet.c b/src/examples/minimal_example_comet.c @@ -74,7 +74,7 @@ main (int argc, char *const *argv) printf ("%s PORT\n", argv[0]); return 1; } - d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + d = MHD_start_daemon (MHD_USE_AUTO | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, atoi (argv[1]), NULL, NULL, &ahc_echo, NULL, MHD_OPTION_END); if (d == NULL) diff --git a/src/examples/upgrade_example.c b/src/examples/upgrade_example.c @@ -275,7 +275,7 @@ main (int argc, printf ("%s PORT\n", argv[0]); return 1; } - d = MHD_start_daemon (MHD_ALLOW_UPGRADE | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, + d = MHD_start_daemon (MHD_ALLOW_UPGRADE | MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, atoi (argv[1]), NULL, NULL, &ahc_echo, NULL, diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -126,7 +126,7 @@ typedef intptr_t ssize_t; * Current version of the library. * 0x01093001 = 1.9.30-1. */ -#define MHD_VERSION 0x00095207 +#define MHD_VERSION 0x00095208 /** * MHD-internal return code for "YES". @@ -761,7 +761,28 @@ enum MHD_FLAG * "Upgrade" may require usage of additional internal resources, * which we do not want to use unless necessary. */ - MHD_ALLOW_UPGRADE = 32768 + MHD_ALLOW_UPGRADE = 32768, + + /** + * Automatically use best available polling function. + * Choice of polling function is also depend on other daemon options. + * If #MHD_USE_INTERNAL_POLLING_THREAD is specified then epoll, poll() or + * select() will be used (listed in decreasing preference order, first + * function available on system will be used). + * If #MHD_USE_THREAD_PER_CONNECTION is specified then poll() or select() + * will be used. + * If those flags are not specified then epoll or select() will be + * used (as the only suitable for MHD_get_fdset()) + */ + MHD_USE_AUTO = 65536, + + /** + * Run using an internal thread (or thread pool) with best available on + * system polling function. + * This is combination of #MHD_USE_AUTO and #MHD_USE_INTERNAL_POLLING_THREAD + * flags. + */ + MHD_USE_AUTO_INTERNAL_THREAD = MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD }; diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -4762,9 +4762,43 @@ MHD_start_daemon_va (unsigned int flags, /* Check for invalid combinations of flags. */ if ( ((0 != (flags & MHD_USE_POLL)) && (0 != (flags & MHD_USE_EPOLL))) || ((0 != (flags & MHD_USE_EPOLL)) && (0 != (flags & MHD_USE_THREAD_PER_CONNECTION))) || - ((0 != (flags & MHD_USE_POLL)) && (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD))) ) + ((0 != (flags & MHD_USE_POLL)) && (0 == (flags & MHD_USE_INTERNAL_POLLING_THREAD))) || + ((0 != (flags & MHD_USE_AUTO)) && (0 != (flags & (MHD_USE_POLL | MHD_USE_EPOLL)))) ) return NULL; + if (0 != (flags & MHD_USE_AUTO)) + { + if (0 != (flags & MHD_USE_THREAD_PER_CONNECTION)) + { + /* Thread per connection with internal polling thread. */ +#ifdef HAVE_POLL + flags |= MHD_USE_POLL; +#else /* ! HAVE_POLL */ + /* use select() - do not modify flags */ +#endif /* ! HAVE_POLL */ + } + else if (0 != (flags & MHD_USE_INTERNAL_POLLING_THREAD)) + { + /* Internal polling thread. */ +#if defined(EPOLL_SUPPORT) + flags |= MHD_USE_EPOLL; +#elif defined(HAVE_POLL) + flags |= MHD_USE_POLL; +#else /* !HAVE_POLL && !EPOLL_SUPPORT */ + /* use select() - do not modify flags */ +#endif /* !HAVE_POLL && !EPOLL_SUPPORT */ + } + else + { + /* Internal threads are not used - "external" polling mode. */ +#if defined(EPOLL_SUPPORT) + flags |= MHD_USE_EPOLL; +#else /* ! EPOLL_SUPPORT */ + /* use select() - do not modify flags */ +#endif /* ! EPOLL_SUPPORT */ + } + } + if (NULL == (daemon = MHD_calloc_ (1, sizeof (struct MHD_Daemon)))) return NULL; #ifdef EPOLL_SUPPORT diff --git a/src/microhttpd/test_upgrade.c b/src/microhttpd/test_upgrade.c @@ -1146,6 +1146,16 @@ main (int argc, fprintf (stderr, "FAILED: Upgrade with external select, return code %d.\n", res); else if (verbose) printf ("PASSED: Upgrade with external select.\n"); + + /* Try external auto */ + res = test_upgrade (MHD_USE_AUTO, + 0); + error_count += res; + if (res) + fprintf (stderr, "FAILED: Upgrade with external 'auto', return code %d.\n", res); + else if (verbose) + printf ("PASSED: Upgrade with external 'auto'.\n"); + #ifdef EPOLL_SUPPORT res = test_upgrade (MHD_USE_EPOLL, 0); @@ -1164,6 +1174,14 @@ main (int argc, fprintf (stderr, "FAILED: Upgrade with thread per connection, return code %d.\n", res); else if (verbose) printf ("PASSED: Upgrade with thread per connection.\n"); + + res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION, + 0); + error_count += res; + if (res) + fprintf (stderr, "FAILED: Upgrade with thread per connection and 'auto', return code %d.\n", res); + else if (verbose) + printf ("PASSED: Upgrade with thread per connection and 'auto'.\n"); #ifdef HAVE_POLL res = test_upgrade (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_POLL, 0); @@ -1189,6 +1207,20 @@ main (int argc, fprintf (stderr, "FAILED: Upgrade with internal select with thread pool, return code %d.\n", res); else if (verbose) printf ("PASSED: Upgrade with internal select with thread pool.\n"); + res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, + 0); + error_count += res; + if (res) + fprintf (stderr, "FAILED: Upgrade with internal 'auto' return code %d.\n", res); + else if (verbose) + printf ("PASSED: Upgrade with internal 'auto'.\n"); + res = test_upgrade (MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD, + 2); + error_count += res; + if (res) + fprintf (stderr, "FAILED: Upgrade with internal 'auto' with thread pool, return code %d.\n", res); + else if (verbose) + printf ("PASSED: Upgrade with internal 'auto' with thread pool.\n"); #ifdef HAVE_POLL res = test_upgrade (MHD_USE_POLL_INTERNAL_THREAD, 0); diff --git a/src/testcurl/perf_get.c b/src/testcurl/perf_get.c @@ -226,7 +226,8 @@ testInternalGet (int port, int poll_flag) } curl_easy_cleanup (c); } - stop (poll_flag == MHD_USE_POLL ? "internal thread with poll()" : + stop (poll_flag == MHD_USE_AUTO ? "internal thread with 'auto'" : + poll_flag == MHD_USE_POLL ? "internal thread with poll()" : poll_flag == MHD_USE_EPOLL ? "internal thread with epoll" : "internal thread with select()"); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) @@ -286,7 +287,8 @@ testMultithreadedGet (int port, int poll_flag) } curl_easy_cleanup (c); } - stop ((poll_flag & MHD_USE_POLL) ? "internal thread with poll() and thread per connection" : + stop ((poll_flag & MHD_USE_AUTO) ? "internal thread with 'auto' and thread per connection" : + (poll_flag & MHD_USE_POLL) ? "internal thread with poll() and thread per connection" : (poll_flag & MHD_USE_EPOLL) ? "internal thread with epoll and thread per connection" : "internal thread with select() and thread per connection"); MHD_stop_daemon (d); @@ -347,7 +349,8 @@ testMultithreadedPoolGet (int port, int poll_flag) } curl_easy_cleanup (c); } - stop (0 != (poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" : + stop (0 != (poll_flag & MHD_USE_AUTO) ? "internal thread pool with 'auto'" : + 0 != (poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" : 0 != (poll_flag & MHD_USE_EPOLL) ? "internal thread pool with epoll" : "internal thread pool with select()"); MHD_stop_daemon (d); if (cbc.pos != strlen ("/hello_world")) @@ -521,6 +524,9 @@ main (int argc, char *const *argv) "/hello_world", MHD_RESPMEM_MUST_COPY); errorCount += testExternalGet (port++); + errorCount += testInternalGet (port++, MHD_USE_AUTO); + errorCount += testMultithreadedGet (port++, MHD_USE_AUTO); + errorCount += testMultithreadedPoolGet (port++, MHD_USE_AUTO); errorCount += testInternalGet (port++, 0); errorCount += testMultithreadedGet (port++, 0); errorCount += testMultithreadedPoolGet (port++, 0); diff --git a/src/testcurl/perf_get_concurrent.c b/src/testcurl/perf_get_concurrent.c @@ -233,7 +233,8 @@ static int testInternalGet (int port, int poll_flag) { struct MHD_Daemon *d; - const char * const test_desc = ((poll_flag & MHD_USE_POLL) ? "internal thread with poll()" : + const char * const test_desc = ((poll_flag & MHD_USE_AUTO) ? "internal thread with 'auto'" : + (poll_flag & MHD_USE_POLL) ? "internal thread with poll()" : (poll_flag & MHD_USE_EPOLL) ? "internal thread with epoll" : "internal thread with select()"); const char * ret_val; @@ -260,7 +261,8 @@ static int testMultithreadedGet (int port, int poll_flag) { struct MHD_Daemon *d; - const char * const test_desc = ((poll_flag & MHD_USE_POLL) ? "internal thread with poll() and thread per connection" : + const char * const test_desc = ((poll_flag & MHD_USE_AUTO) ? "internal thread with 'auto' and thread per connection" : + (poll_flag & MHD_USE_POLL) ? "internal thread with poll() and thread per connection" : (poll_flag & MHD_USE_EPOLL) ? "internal thread with epoll and thread per connection" : "internal thread with select() and thread per connection"); const char * ret_val; @@ -287,7 +289,8 @@ static int testMultithreadedPoolGet (int port, int poll_flag) { struct MHD_Daemon *d; - const char * const test_desc = ((poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" : + const char * const test_desc = ((poll_flag & MHD_USE_AUTO) ? "internal thread pool with 'auto'" : + (poll_flag & MHD_USE_POLL) ? "internal thread pool with poll()" : (poll_flag & MHD_USE_EPOLL) ? "internal thread poll with epoll" : "internal thread pool with select()"); const char * ret_val; @@ -395,6 +398,9 @@ main (int argc, char *const *argv) errorCount += testMultithreadedGet (port++, 0); errorCount += testMultithreadedPoolGet (port++, 0); errorCount += testExternalGet (port++); + errorCount += testInternalGet (port++, MHD_USE_AUTO); + errorCount += testMultithreadedGet (port++, MHD_USE_AUTO); + errorCount += testMultithreadedPoolGet (port++, MHD_USE_AUTO); if (MHD_YES == MHD_is_feature_supported(MHD_FEATURE_POLL)) { errorCount += testInternalGet (port++, MHD_USE_POLL);