aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-03-01 15:09:14 +0000
committerChristian Grothoff <christian@grothoff.org>2011-03-01 15:09:14 +0000
commit260dd93fdabe89e8c715286c20e23124a79c2b54 (patch)
treebca1fd848f95def607f35e1dabad90eab106e7b0
parentd4a325b3edd24ba5ac1957898fd089b3a810a84f (diff)
downloadlibmicrohttpd-260dd93fdabe89e8c715286c20e23124a79c2b54.tar.gz
libmicrohttpd-260dd93fdabe89e8c715286c20e23124a79c2b54.zip
enable poll more broadly, fix timeout, use pipe instead of signal
-rw-r--r--ChangeLog5
-rw-r--r--src/daemon/daemon.c380
-rw-r--r--src/daemon/internal.h5
-rw-r--r--src/examples/minimal_example.c5
-rw-r--r--src/include/microhttpd.h2
5 files changed, 237 insertions, 160 deletions
diff --git a/ChangeLog b/ChangeLog
index c0424fcb..d3b01a42 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
1Tue Mar 1 13:58:04 CET 2011
2 Allow use of 'poll' in combination with the external select mode.
3 Avoid using pthread signals (SIGALRM), use pipe instead.
4 Corrected timeout calculation (s vs. ms). -CG
5
1Wed Feb 23 14:21:44 CET 2011 6Wed Feb 23 14:21:44 CET 2011
2 Removing useless code pointed out by Eivind Sarto. -CG 7 Removing useless code pointed out by Eivind Sarto. -CG
3 8
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index d2e356a9..460e057e 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -80,14 +80,6 @@
80#endif 80#endif
81#endif 81#endif
82 82
83#ifdef __SYMBIAN32__
84static void pthread_kill (int, int) {
85 // Symbian doesn't have signals. The user of the library is required to
86 // run it in an external select loop.
87 abort();
88}
89#endif // __SYMBIAN32__
90
91/** 83/**
92 * Default implementation of the panic function 84 * Default implementation of the panic function
93 */ 85 */
@@ -572,45 +564,54 @@ MHD_handle_connection (void *data)
572 fd_set es; 564 fd_set es;
573 int max; 565 int max;
574 struct timeval tv; 566 struct timeval tv;
567 struct timeval *tvp;
575 unsigned int timeout; 568 unsigned int timeout;
569 time_t now;
576#ifdef HAVE_POLL_H 570#ifdef HAVE_POLL_H
577 struct MHD_Pollfd mp; 571 struct MHD_Pollfd mp;
578 struct pollfd p; 572 struct pollfd p[2];
579#endif 573#endif
580 574
581 timeout = con->daemon->connection_timeout; 575 timeout = con->daemon->connection_timeout;
582 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) { 576 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) {
583 tv.tv_usec = 0; 577 tvp = NULL;
584 if ( (timeout > (time (NULL) - con->last_activity)) || 578 if (timeout > 0)
585 (timeout == 0) )
586 { 579 {
587 /* in case we are missing the SIGALRM, keep going after 580 now = time (NULL);
588 at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */ 581 if (now - con->last_activity > timeout)
589 tv.tv_sec = 1; 582 tv.tv_sec = 0;
590 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) || 583 else
591 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY)) 584 tv.tv_sec = timeout - (now - con->last_activity);
592 { 585 tvp = &tv;
593 /* do not block (we're waiting for our callback to succeed) */
594 tv.tv_sec = 0;
595 }
596 } 586 }
597 else 587 if ((con->state == MHD_CONNECTION_NORMAL_BODY_UNREADY) ||
588 (con->state == MHD_CONNECTION_CHUNKED_BODY_UNREADY))
598 { 589 {
590 /* do not block (we're waiting for our callback to succeed) */
599 tv.tv_sec = 0; 591 tv.tv_sec = 0;
592 tv.tv_usec = 0;
593 tvp = &tv;
600 } 594 }
601#ifdef HAVE_POLL_H 595#ifdef HAVE_POLL_H
602 if (0 == (con->daemon->options & MHD_USE_POLL)) { 596 if (0 == (con->daemon->options & MHD_USE_POLL))
597 {
603#else 598#else
604 { 599 {
605#endif 600#endif
606 /* use select */ 601 /* use select */
607 FD_ZERO (&rs); 602 FD_ZERO (&rs);
608 FD_ZERO (&ws); 603 FD_ZERO (&ws);
609 FD_ZERO (&es); 604 FD_ZERO (&es);
610 max = 0; 605 if (-1 != con->daemon->wpipe[0])
611 MHD_connection_get_fdset (con, &rs, &ws, &es, &max); 606 {
612 num_ready = SELECT (max + 1, &rs, &ws, &es, &tv); 607 max = con->daemon->wpipe[0];
613 if (num_ready < 0) { 608 FD_SET (con->daemon->wpipe[0], &rs);
609 }
610 else
611 max = 0;
612 MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
613 num_ready = SELECT (max + 1, &rs, &ws, &es, tvp);
614 if (num_ready < 0) {
614 if (errno == EINTR) 615 if (errno == EINTR)
615 continue; 616 continue;
616#if HAVE_MESSAGES 617#if HAVE_MESSAGES
@@ -618,52 +619,54 @@ MHD_handle_connection (void *data)
618 STRERROR (errno)); 619 STRERROR (errno));
619#endif 620#endif
620 break; 621 break;
621 } 622 }
622 /* call appropriate connection handler if necessary */ 623 /* call appropriate connection handler if necessary */
623 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs))) 624 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs)))
624 con->read_handler (con); 625 con->read_handler (con);
625 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws))) 626 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
626 con->write_handler (con); 627 con->write_handler (con);
627 if (con->socket_fd != -1) 628 if (con->socket_fd != -1)
628 con->idle_handler (con); 629 con->idle_handler (con);
629 } 630 }
630#ifdef HAVE_POLL_H 631#ifdef HAVE_POLL_H
631 else 632 else
632 { 633 {
633 /* use poll */ 634 /* use poll */
634 memset(&mp, 0, sizeof (struct MHD_Pollfd)); 635 memset(&mp, 0, sizeof (struct MHD_Pollfd));
635 MHD_connection_get_pollfd(con, &mp); 636 MHD_connection_get_pollfd(con, &mp);
636 memset(&p, 0, sizeof (struct pollfd)); 637 memset(&p, 0, sizeof (p));
637 p.fd = mp.fd; 638 p[0].fd = mp.fd;
638 if (mp.events & MHD_POLL_ACTION_IN) 639 if (mp.events & MHD_POLL_ACTION_IN)
639 p.events |= POLLIN; 640 p[0].events |= POLLIN;
640 if (mp.events & MHD_POLL_ACTION_OUT) 641 if (mp.events & MHD_POLL_ACTION_OUT)
641 p.events |= POLLOUT; 642 p[0].events |= POLLOUT;
642 /* in case we are missing the SIGALRM, keep going after 643 p[1].fd = con->daemon->wpipe[0];
643 at most 1s */ 644 p[1].events |= POLLIN;
644 if (poll (&p, 1, 1000) < 0) { 645
645 if (errno == EINTR) 646 if (poll (p, 2, (tvp == NULL) ? -1 : (tv.tv_sec * 1000)) < 0)
646 continue; 647 {
648 if (errno == EINTR)
649 continue;
647#if HAVE_MESSAGES 650#if HAVE_MESSAGES
648 MHD_DLOG (con->daemon, "Error during poll: `%s'\n", 651 MHD_DLOG (con->daemon, "Error during poll: `%s'\n",
649 STRERROR (errno)); 652 STRERROR (errno));
650#endif 653#endif
651 break; 654 break;
652 } 655 }
653 if ( (con->socket_fd != -1) && 656 if ( (con->socket_fd != -1) &&
654 (0 != (p.revents & POLLIN)) ) 657 (0 != (p[0].revents & POLLIN)) )
655 con->read_handler (con); 658 con->read_handler (con);
656 if ( (con->socket_fd != -1) && 659 if ( (con->socket_fd != -1) &&
657 (0 != (p.revents & POLLOUT)) ) 660 (0 != (p[0].revents & POLLOUT)) )
658 con->write_handler (con); 661 con->write_handler (con);
659 if (con->socket_fd != -1) 662 if (con->socket_fd != -1)
660 con->idle_handler (con); 663 con->idle_handler (con);
661 if ( (con->socket_fd != -1) && 664 if ( (con->socket_fd != -1) &&
662 (0 != (p.revents & (POLLERR | POLLHUP))) ) 665 (0 != (p[0].revents & (POLLERR | POLLHUP))) )
663 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR); 666 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
664 } 667 }
665#endif 668#endif
666 } 669 }
667 if (con->socket_fd != -1) 670 if (con->socket_fd != -1)
668 { 671 {
669#if DEBUG_CLOSE 672#if DEBUG_CLOSE
@@ -1085,7 +1088,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
1085 prev->next = pos->next; 1088 prev->next = pos->next;
1086 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 1089 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1087 { 1090 {
1088 pthread_kill (pos->pid, SIGALRM); 1091
1089 if (0 != (rc = pthread_join (pos->pid, &unused))) 1092 if (0 != (rc = pthread_join (pos->pid, &unused)))
1090 { 1093 {
1091#if HAVE_MESSAGES 1094#if HAVE_MESSAGES
@@ -1148,7 +1151,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
1148 return MHD_NO; /* no connections */ 1151 return MHD_NO; /* no connections */
1149 now = time (NULL); 1152 now = time (NULL);
1150 /* start with conservative estimate */ 1153 /* start with conservative estimate */
1151 earliest_deadline = now + dto; 1154 earliest_deadline = now + dto + 1;
1152 while (pos != NULL) 1155 while (pos != NULL)
1153 { 1156 {
1154 if (earliest_deadline > pos->last_activity + dto) 1157 if (earliest_deadline > pos->last_activity + dto)
@@ -1163,7 +1166,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, unsigned MHD_LONG_LONG *timeout)
1163 if (earliest_deadline < now) 1166 if (earliest_deadline < now)
1164 *timeout = 0; 1167 *timeout = 0;
1165 else 1168 else
1166 *timeout = (earliest_deadline - now); 1169 *timeout = 1000 * (1 + earliest_deadline - now);
1167 return MHD_YES; 1170 return MHD_YES;
1168} 1171}
1169 1172
@@ -1185,6 +1188,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
1185 fd_set es; 1188 fd_set es;
1186 int max; 1189 int max;
1187 struct timeval timeout; 1190 struct timeval timeout;
1191 struct timeval *tv;
1188 unsigned MHD_LONG_LONG ltimeout; 1192 unsigned MHD_LONG_LONG ltimeout;
1189 int ds; 1193 int ds;
1190 1194
@@ -1195,8 +1199,13 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
1195 FD_ZERO (&rs); 1199 FD_ZERO (&rs);
1196 FD_ZERO (&ws); 1200 FD_ZERO (&ws);
1197 FD_ZERO (&es); 1201 FD_ZERO (&es);
1198 max = 0; 1202 if (-1 != daemon->wpipe[0])
1199 1203 {
1204 max = daemon->wpipe[0];
1205 FD_SET (daemon->wpipe[0], &rs);
1206 }
1207 else
1208 max = 0;
1200 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 1209 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1201 { 1210 {
1202 /* single-threaded, go over everything */ 1211 /* single-threaded, go over everything */
@@ -1217,26 +1226,21 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
1217 FD_SET (max, &rs); 1226 FD_SET (max, &rs);
1218 } 1227 }
1219 1228
1220 /* in case we are missing the SIGALRM, keep going after 1229 tv = NULL;
1221 at most 1s; see http://lists.gnu.org/archive/html/libmicrohttpd/2009-10/msg00013.html */
1222 timeout.tv_usec = 0;
1223 timeout.tv_sec = 1;
1224 if (may_block == MHD_NO) 1230 if (may_block == MHD_NO)
1225 { 1231 {
1226 timeout.tv_usec = 0; 1232 timeout.tv_usec = 0;
1227 timeout.tv_sec = 0; 1233 timeout.tv_sec = 0;
1234 tv = &timeout;
1228 } 1235 }
1229 else 1236 else if (MHD_YES == MHD_get_timeout (daemon, &ltimeout))
1230 { 1237 {
1231 /* ltimeout is in ms */ 1238 /* ltimeout is in ms */
1232 if ( (MHD_YES == MHD_get_timeout (daemon, &ltimeout)) && 1239 timeout.tv_usec = (ltimeout % 1000) * 1000;
1233 (ltimeout < 1000) ) 1240 timeout.tv_sec = ltimeout / 1000;
1234 { 1241 tv = &timeout;
1235 timeout.tv_usec = ltimeout * 1000;
1236 timeout.tv_sec = 0;
1237 }
1238 } 1242 }
1239 num_ready = SELECT (max + 1, &rs, &ws, &es, &timeout); 1243 num_ready = SELECT (max + 1, &rs, &ws, &es, tv);
1240 1244
1241 if (daemon->shutdown == MHD_YES) 1245 if (daemon->shutdown == MHD_YES)
1242 return MHD_NO; 1246 return MHD_NO;
@@ -1279,38 +1283,93 @@ MHD_select (struct MHD_Daemon *daemon, int may_block)
1279 return MHD_YES; 1283 return MHD_YES;
1280} 1284}
1281 1285
1286
1282/** 1287/**
1283 * Poll for new connection. Used only with THREAD_PER_CONNECTION 1288 * Poll for new connection.
1284 * 1289 *
1285 * @param daemon daemon to run poll loop for 1290 * @param daemon daemon to run poll loop for
1291 * @param may_block YES if blocking, NO if non-blocking
1292 * @return MHD_NO on serious errors, MHD_YES on success
1286 */ 1293 */
1287static int 1294static int
1288MHD_poll (struct MHD_Daemon *daemon) 1295MHD_poll (struct MHD_Daemon *daemon,
1296 int may_block)
1289{ 1297{
1290#ifdef HAVE_POLL_H 1298#ifdef HAVE_POLL_H
1291 struct pollfd p; 1299 unsigned int num_connections;
1292 1300 struct MHD_Connection *pos;
1293 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1294 return MHD_NO;
1295 p.fd = daemon->socket_fd;
1296 p.events = POLLIN;
1297 p.revents = 0;
1298 1301
1299 if (poll(&p, 1, 1000) < 0) { 1302 num_connections = 0;
1300 if (errno == EINTR) 1303 pos = daemon->connections;
1301 return MHD_YES; 1304 while (pos != NULL)
1305 {
1306 num_connections++;
1307 pos = pos->next;
1308 }
1309 {
1310 struct pollfd p[2 + num_connections];
1311 struct MHD_Pollfd mp;
1312 unsigned MHD_LONG_LONG ltimeout;
1313 unsigned int i;
1314 int timeout;
1315
1316 p[0].fd = daemon->socket_fd;
1317 p[0].events = POLLIN;
1318 p[0].revents = 0;
1319 p[1].fd = daemon->wpipe[0];
1320 p[1].events = POLLIN;
1321 p[1].revents = 0;
1322 if (may_block == MHD_NO)
1323 timeout = 0;
1324 else if (MHD_YES != MHD_get_timeout (daemon, &ltimeout))
1325 timeout = -1;
1326 else
1327 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
1328
1329 i = 0;
1330 pos = daemon->connections;
1331 while (pos != NULL)
1332 {
1333 memset(&mp, 0, sizeof (struct MHD_Pollfd));
1334 MHD_connection_get_pollfd (pos, &mp);
1335 memset(&p, 0, sizeof (p));
1336 p[2+i].fd = mp.fd;
1337 if (mp.events & MHD_POLL_ACTION_IN)
1338 p[2+i].events |= POLLIN;
1339 if (mp.events & MHD_POLL_ACTION_OUT)
1340 p[2+i].events |= POLLOUT;
1341 i++;
1342 pos = pos->next;
1343 }
1344 if (poll (p, 2 + num_connections, timeout) < 0) {
1345 if (errno == EINTR)
1346 return MHD_YES;
1302#if HAVE_MESSAGES 1347#if HAVE_MESSAGES
1303 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); 1348 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
1304#endif 1349#endif
1305 return MHD_NO; 1350 return MHD_NO;
1351 }
1352 /* handle shutdown cases */
1353 if (daemon->shutdown == MHD_YES)
1354 return MHD_NO;
1355 if (daemon->socket_fd < 0)
1356 return MHD_YES;
1357 if (0 != (p[0].revents & POLLIN))
1358 MHD_accept_connection (daemon);
1359 i = 0;
1360 pos = daemon->connections;
1361 while (pos != NULL)
1362 {
1363 if (0 != (p[2+i].revents & POLLIN))
1364 pos->read_handler (pos);
1365 if (0 != (p[2+i].revents & POLLOUT))
1366 pos->write_handler (pos);
1367 if (pos->socket_fd != -1)
1368 pos->idle_handler (pos);
1369 i++;
1370 pos = pos->next;
1371 }
1306 } 1372 }
1307 /* handle shutdown cases */
1308 if (daemon->shutdown == MHD_YES)
1309 return MHD_NO;
1310 if (daemon->socket_fd < 0)
1311 return MHD_YES;
1312 if (0 != (p.revents & POLLIN))
1313 MHD_accept_connection (daemon);
1314 return MHD_YES; 1373 return MHD_YES;
1315#else 1374#else
1316 return MHD_NO; 1375 return MHD_NO;
@@ -1335,7 +1394,10 @@ MHD_run (struct MHD_Daemon *daemon)
1335 & MHD_USE_THREAD_PER_CONNECTION)) 1394 & MHD_USE_THREAD_PER_CONNECTION))
1336 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) 1395 || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
1337 return MHD_NO; 1396 return MHD_NO;
1338 MHD_select (daemon, MHD_NO); 1397 if ((daemon->options & MHD_USE_POLL) == 0)
1398 MHD_select (daemon, MHD_NO);
1399 else
1400 MHD_poll (daemon, MHD_NO);
1339 MHD_cleanup_connections (daemon); 1401 MHD_cleanup_connections (daemon);
1340 return MHD_YES; 1402 return MHD_YES;
1341} 1403}
@@ -1357,7 +1419,7 @@ MHD_select_thread (void *cls)
1357 if ((daemon->options & MHD_USE_POLL) == 0) 1419 if ((daemon->options & MHD_USE_POLL) == 0)
1358 MHD_select (daemon, MHD_YES); 1420 MHD_select (daemon, MHD_YES);
1359 else 1421 else
1360 MHD_poll(daemon); 1422 MHD_poll (daemon, MHD_YES);
1361 MHD_cleanup_connections (daemon); 1423 MHD_cleanup_connections (daemon);
1362 } 1424 }
1363 return NULL; 1425 return NULL;
@@ -1725,7 +1787,7 @@ MHD_start_daemon_va (unsigned int options,
1725 } 1787 }
1726#endif 1788#endif
1727 retVal->socket_fd = -1; 1789 retVal->socket_fd = -1;
1728 retVal->options = (enum MHD_OPTION)options; 1790 retVal->options = (enum MHD_OPTION) options;
1729 retVal->port = port; 1791 retVal->port = port;
1730 retVal->apc = apc; 1792 retVal->apc = apc;
1731 retVal->apc_cls = apc_cls; 1793 retVal->apc_cls = apc_cls;
@@ -1735,6 +1797,37 @@ MHD_start_daemon_va (unsigned int options,
1735 retVal->pool_size = MHD_POOL_SIZE_DEFAULT; 1797 retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
1736 retVal->unescape_callback = &MHD_http_unescape; 1798 retVal->unescape_callback = &MHD_http_unescape;
1737 retVal->connection_timeout = 0; /* no timeout */ 1799 retVal->connection_timeout = 0; /* no timeout */
1800 retVal->wpipe[0] = -1;
1801 retVal->wpipe[1] = -1;
1802 if ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
1803 (0 != (options & MHD_USE_SELECT_INTERNALLY)) )
1804 {
1805 if (0 != pipe (retVal->wpipe))
1806 {
1807#if HAVE_MESSAGES
1808 FPRINTF(stderr,
1809 "Failed to create control pipe: %s\n",
1810 STRERROR (errno));
1811#endif
1812 free (retVal);
1813 return NULL;
1814 }
1815#ifndef WINDOWS
1816 if ( (0 == (options & MHD_USE_POLL)) &&
1817 (retVal->wpipe[0] >= FD_SETSIZE) )
1818 {
1819#if HAVE_MESSAGES
1820 FPRINTF(stderr,
1821 "file descriptor for control pipe exceeds maximum value\n");
1822#endif
1823 close (retVal->wpipe[0]);
1824 close (retVal->wpipe[1]);
1825 free (retVal);
1826 return NULL;
1827 }
1828#endif
1829 }
1830
1738#ifdef DAUTH_SUPPORT 1831#ifdef DAUTH_SUPPORT
1739 retVal->digest_auth_rand_size = 0; 1832 retVal->digest_auth_rand_size = 0;
1740 retVal->digest_auth_random = NULL; 1833 retVal->digest_auth_random = NULL;
@@ -1809,22 +1902,6 @@ MHD_start_daemon_va (unsigned int options,
1809 } 1902 }
1810#endif 1903#endif
1811 1904
1812 /* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
1813 if ( (0 != (options & MHD_USE_POLL)) &&
1814 (0 == (options & MHD_USE_THREAD_PER_CONNECTION)) )
1815 {
1816#if HAVE_MESSAGES
1817 MHD_DLOG (retVal,
1818 "MHD poll support only works with MHD_USE_THREAD_PER_CONNECTION\n");
1819#endif
1820#if DAUTH_SUPPORT
1821 free (retVal->nnc);
1822 pthread_mutex_destroy (&retVal->nnc_lock);
1823#endif
1824 free (retVal);
1825 return NULL;
1826 }
1827
1828 /* Thread pooling currently works only with internal select thread model */ 1905 /* Thread pooling currently works only with internal select thread model */
1829 if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) && 1906 if ( (0 == (options & MHD_USE_SELECT_INTERNALLY)) &&
1830 (retVal->worker_pool_size > 0) ) 1907 (retVal->worker_pool_size > 0) )
@@ -2172,12 +2249,15 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2172 int fd; 2249 int fd;
2173 unsigned int i; 2250 unsigned int i;
2174 int rc; 2251 int rc;
2252 char c;
2175 2253
2176 if (daemon == NULL) 2254 if (daemon == NULL)
2177 return; 2255 return;
2178 daemon->shutdown = MHD_YES; 2256 daemon->shutdown = MHD_YES;
2179 fd = daemon->socket_fd; 2257 fd = daemon->socket_fd;
2180 daemon->socket_fd = -1; 2258 daemon->socket_fd = -1;
2259 if (daemon->wpipe[1] != -1)
2260 write (daemon->wpipe[1], "e", 1);
2181 2261
2182 /* Prepare workers for shutdown */ 2262 /* Prepare workers for shutdown */
2183 for (i = 0; i < daemon->worker_pool_size; ++i) 2263 for (i = 0; i < daemon->worker_pool_size; ++i)
@@ -2202,8 +2282,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2202 2282
2203 /* Signal workers to stop and clean them up */ 2283 /* Signal workers to stop and clean them up */
2204 for (i = 0; i < daemon->worker_pool_size; ++i) 2284 for (i = 0; i < daemon->worker_pool_size; ++i)
2205 pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
2206 for (i = 0; i < daemon->worker_pool_size; ++i)
2207 { 2285 {
2208 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) 2286 if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused)))
2209 { 2287 {
@@ -2221,7 +2299,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2221 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) 2299 ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
2222 && (0 == daemon->worker_pool_size))) 2300 && (0 == daemon->worker_pool_size)))
2223 { 2301 {
2224 pthread_kill (daemon->pid, SIGALRM);
2225 if (0 != (rc = pthread_join (daemon->pid, &unused))) 2302 if (0 != (rc = pthread_join (daemon->pid, &unused)))
2226 { 2303 {
2227#if HAVE_MESSAGES 2304#if HAVE_MESSAGES
@@ -2272,6 +2349,15 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2272 pthread_mutex_destroy (&daemon->nnc_lock); 2349 pthread_mutex_destroy (&daemon->nnc_lock);
2273#endif 2350#endif
2274 pthread_mutex_destroy (&daemon->per_ip_connection_mutex); 2351 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
2352
2353 if (daemon->wpipe[1] != -1)
2354 {
2355 /* just to be sure, remove the one char we
2356 wrote into the pipe */
2357 (void) read (daemon->wpipe[0], &c, 1);
2358 close (daemon->wpipe[0]);
2359 close (daemon->wpipe[1]);
2360 }
2275 free (daemon); 2361 free (daemon);
2276} 2362}
2277 2363
@@ -2330,18 +2416,6 @@ MHD_get_version (void)
2330 return PACKAGE_VERSION; 2416 return PACKAGE_VERSION;
2331} 2417}
2332 2418
2333#ifndef WINDOWS
2334
2335static struct sigaction sig;
2336
2337static struct sigaction old;
2338
2339static void
2340sigalrmHandler (int sig)
2341{
2342}
2343#endif
2344
2345#ifdef __GNUC__ 2419#ifdef __GNUC__
2346#define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor)) 2420#define ATTRIBUTE_CONSTRUCTOR __attribute__ ((constructor))
2347#define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor)) 2421#define ATTRIBUTE_DESTRUCTOR __attribute__ ((destructor))
@@ -2355,22 +2429,14 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
2355#endif 2429#endif
2356 2430
2357/** 2431/**
2358 * Initialize the signal handler for SIGALRM 2432 * Initialize do setup work.
2359 * and do other setup work.
2360 */ 2433 */
2361void ATTRIBUTE_CONSTRUCTOR MHD_init () 2434void ATTRIBUTE_CONSTRUCTOR MHD_init ()
2362{ 2435{
2363 mhd_panic = &mhd_panic_std; 2436 mhd_panic = &mhd_panic_std;
2364 mhd_panic_cls = NULL; 2437 mhd_panic_cls = NULL;
2365 2438
2366#ifndef WINDOWS 2439#ifdef WINDOWS
2367 /* make sure SIGALRM does not kill us */
2368 memset (&sig, 0, sizeof (struct sigaction));
2369 memset (&old, 0, sizeof (struct sigaction));
2370 sig.sa_flags = SA_NODEFER;
2371 sig.sa_handler = &sigalrmHandler;
2372 sigaction (SIGALRM, &sig, &old);
2373#else
2374 plibc_init ("GNU", "libmicrohttpd"); 2440 plibc_init ("GNU", "libmicrohttpd");
2375#endif 2441#endif
2376#if HTTPS_SUPPORT 2442#if HTTPS_SUPPORT
@@ -2388,9 +2454,7 @@ void ATTRIBUTE_DESTRUCTOR MHD_fini ()
2388 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex)) 2454 if (0 != pthread_mutex_destroy(&MHD_gnutls_init_mutex))
2389 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); 2455 mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
2390#endif 2456#endif
2391#ifndef WINDOWS 2457#ifdef WINDOWS
2392 sigaction (SIGALRM, &old, &sig);
2393#else
2394 plibc_shutdown (); 2458 plibc_shutdown ();
2395#endif 2459#endif
2396} 2460}
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 9a3eb8cb..ee499cef 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -857,6 +857,11 @@ struct MHD_Daemon
857 int socket_fd; 857 int socket_fd;
858 858
859 /** 859 /**
860 * Pipe we use to signal shutdown.
861 */
862 int wpipe[2];
863
864 /**
860 * Are we shutting down? 865 * Are we shutting down?
861 */ 866 */
862 int shutdown; 867 int shutdown;
diff --git a/src/examples/minimal_example.c b/src/examples/minimal_example.c
index 9293242b..8c7d17d9 100644
--- a/src/examples/minimal_example.c
+++ b/src/examples/minimal_example.c
@@ -67,7 +67,10 @@ main (int argc, char *const *argv)
67 printf ("%s PORT\n", argv[0]); 67 printf ("%s PORT\n", argv[0]);
68 return 1; 68 return 1;
69 } 69 }
70 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG, 70 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | MHD_USE_POLL,
71 // MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
72 // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG | MHD_USE_POLL,
73 // MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
71 atoi (argv[1]), 74 atoi (argv[1]),
72 NULL, NULL, &ahc_echo, PAGE, 75 NULL, NULL, &ahc_echo, PAGE,
73 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 5, 76 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 5,
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 881ff312..3f3b61de 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -106,7 +106,7 @@ extern "C"
106/** 106/**
107 * Current version of the library. 107 * Current version of the library.
108 */ 108 */
109#define MHD_VERSION 0x00090702 109#define MHD_VERSION 0x00090703
110 110
111/** 111/**
112 * MHD-internal return code for "YES". 112 * MHD-internal return code for "YES".