aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-06-21 13:00:30 +0000
committerChristian Grothoff <christian@grothoff.org>2011-06-21 13:00:30 +0000
commit901090b07ba9c89e086072b14768a24241f6714c (patch)
tree9a7c95de963fc3a472ced2e3c668398676af4c90
parent94bb1bb839e1dbb9e84f0b3a31cc8689df9a9d54 (diff)
downloadlibmicrohttpd-901090b07ba9c89e086072b14768a24241f6714c.tar.gz
libmicrohttpd-901090b07ba9c89e086072b14768a24241f6714c.zip
fixing race condition, minor leak, O(n) shutdown is now O(1)
-rw-r--r--ChangeLog7
-rw-r--r--src/daemon/connection.c225
-rw-r--r--src/daemon/connection_https.c55
-rw-r--r--src/daemon/daemon.c289
-rw-r--r--src/daemon/internal.h85
5 files changed, 387 insertions, 274 deletions
diff --git a/ChangeLog b/ChangeLog
index b41242e1..09d5f798 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
1Tue Jun 21 13:54:59 CEST 2011
2 Fixing tiny memory leak in SSL code from 'gnutls_priority_init'.
3 Fixing data race between code doing connection shutdown and
4 connection cleanup.
5 Changing code to reduce connection cleanup cost from O(n) to O(1).
6 Cleaning up logging code around 'connection_close_error'. -CG
7
1Sat Jun 11 13:05:12 CEST 2011 8Sat Jun 11 13:05:12 CEST 2011
2 Replacing use of sscanf by strtoul (#1688). -CG/bplant 9 Replacing use of sscanf by strtoul (#1688). -CG/bplant
3 10
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index 33571ea9..54cbb17d 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -275,6 +275,7 @@ need_100_continue (struct MHD_Connection *connection)
275 strlen (HTTP_100_CONTINUE))); 275 strlen (HTTP_100_CONTINUE)));
276} 276}
277 277
278
278/** 279/**
279 * Close the given connection and give the 280 * Close the given connection and give the
280 * specified termination code to the user. 281 * specified termination code to the user.
@@ -283,31 +284,52 @@ void
283MHD_connection_close (struct MHD_Connection *connection, 284MHD_connection_close (struct MHD_Connection *connection,
284 enum MHD_RequestTerminationCode termination_code) 285 enum MHD_RequestTerminationCode termination_code)
285{ 286{
287 struct MHD_Daemon *daemon;
288
289 daemon = connection->daemon;
286 SHUTDOWN (connection->socket_fd, SHUT_RDWR); 290 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
287 CLOSE (connection->socket_fd);
288 connection->socket_fd = -1;
289 connection->state = MHD_CONNECTION_CLOSED; 291 connection->state = MHD_CONNECTION_CLOSED;
290 if ( (NULL != connection->daemon->notify_completed) && 292 if ( (NULL != daemon->notify_completed) &&
291 (MHD_YES == connection->client_aware) ) 293 (MHD_YES == connection->client_aware) )
292 connection->daemon->notify_completed (connection->daemon-> 294 daemon->notify_completed (daemon->notify_completed_cls,
293 notify_completed_cls, connection, 295 connection,
294 &connection->client_context, 296 &connection->client_context,
295 termination_code); 297 termination_code);
296 connection->client_aware = MHD_NO; 298 connection->client_aware = MHD_NO;
297} 299}
298 300
301
299/** 302/**
300 * A serious error occured, close the 303 * A serious error occured, close the
301 * connection (and notify the application). 304 * connection (and notify the application).
305 *
306 * @param connection connection to close with error
307 * @param emsg error message (can be NULL)
302 */ 308 */
303static void 309static void
304connection_close_error (struct MHD_Connection *connection) 310connection_close_error (struct MHD_Connection *connection,
311 const char *emsg)
305{ 312{
313#if HAVE_MESSAGES
314 if (NULL != emsg)
315 MHD_DLOG (connection->daemon, emsg);
316#endif
306 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR); 317 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_WITH_ERROR);
307} 318}
308 319
309 320
310/** 321/**
322 * Macro to only include error message in call to
323 * "connection_close_error" if we have HAVE_MESSAGES.
324 */
325#if HAVE_MESSAGES
326#define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
327#else
328#define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
329#endif
330
331
332/**
311 * Prepare the response buffer of this connection for 333 * Prepare the response buffer of this connection for
312 * sending. Assumes that the response mutex is 334 * sending. Assumes that the response mutex is
313 * already held. If the transmission is complete, 335 * already held. If the transmission is complete,
@@ -357,16 +379,12 @@ try_ready_normal_body (struct MHD_Connection *connection)
357 if ( (ret == MHD_CONTENT_READER_END_OF_STREAM) || 379 if ( (ret == MHD_CONTENT_READER_END_OF_STREAM) ||
358 (ret == MHD_CONTENT_READER_END_WITH_ERROR) ) 380 (ret == MHD_CONTENT_READER_END_WITH_ERROR) )
359 { 381 {
360 /* either error or http 1.0 transfer, close 382 /* either error or http 1.0 transfer, close socket! */
361 socket! */
362#if DEBUG_CLOSE
363#if HAVE_MESSAGES
364 MHD_DLOG (connection->daemon,
365 "Closing connection (end of response or error)\n");
366#endif
367#endif
368 response->total_size = connection->response_write_position; 383 response->total_size = connection->response_write_position;
369 connection_close_error (connection); 384 CONNECTION_CLOSE_ERROR (connection,
385 (ret == MHD_CONTENT_READER_END_OF_STREAM)
386 ? "Closing connection (end of response)\n"
387 : "Closing connection (stream error)\n");
370 return MHD_NO; 388 return MHD_NO;
371 } 389 }
372 response->data_start = connection->response_write_position; 390 response->data_start = connection->response_write_position;
@@ -405,13 +423,8 @@ try_ready_chunked_body (struct MHD_Connection *connection)
405 if (size < 128) 423 if (size < 128)
406 { 424 {
407 /* not enough memory */ 425 /* not enough memory */
408#if DEBUG_CLOSE 426 CONNECTION_CLOSE_ERROR (connection,
409#if HAVE_MESSAGES 427 "Closing connection (out of memory)\n");
410 MHD_DLOG (connection->daemon,
411 "Closing connection (out of memory)\n");
412#endif
413#endif
414 connection_close_error (connection);
415 return MHD_NO; 428 return MHD_NO;
416 } 429 }
417 buf = MHD_pool_allocate (connection->pool, size, MHD_NO); 430 buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
@@ -445,14 +458,9 @@ try_ready_chunked_body (struct MHD_Connection *connection)
445 if (ret == MHD_CONTENT_READER_END_WITH_ERROR) 458 if (ret == MHD_CONTENT_READER_END_WITH_ERROR)
446 { 459 {
447 /* error, close socket! */ 460 /* error, close socket! */
448#if DEBUG_CLOSE
449#if HAVE_MESSAGES
450 MHD_DLOG (connection->daemon,
451 "Closing connection (error generating response)\n");
452#endif
453#endif
454 response->total_size = connection->response_write_position; 461 response->total_size = connection->response_write_position;
455 connection_close_error (connection); 462 CONNECTION_CLOSE_ERROR (connection,
463 "Closing connection (error generating response)\n");
456 return MHD_NO; 464 return MHD_NO;
457 } 465 }
458 if (ret == MHD_CONTENT_READER_END_OF_STREAM) 466 if (ret == MHD_CONTENT_READER_END_OF_STREAM)
@@ -722,11 +730,8 @@ transmit_error_response (struct MHD_Connection *connection,
722 if (MHD_NO == build_header_response (connection)) 730 if (MHD_NO == build_header_response (connection))
723 { 731 {
724 /* oops - close! */ 732 /* oops - close! */
725#if HAVE_MESSAGES 733 CONNECTION_CLOSE_ERROR (connection,
726 MHD_DLOG (connection->daemon, 734 "Closing connection (failed to create response header)\n");
727 "Closing connection (failed to create response header)\n");
728#endif
729 connection->state = MHD_CONNECTION_CLOSED;
730 } 735 }
731 else 736 else
732 { 737 {
@@ -788,11 +793,9 @@ MHD_connection_get_pollfd (struct MHD_Connection *connection, struct MHD_Pollfd
788 connection->pool = MHD_pool_create (connection->daemon->pool_size); 793 connection->pool = MHD_pool_create (connection->daemon->pool_size);
789 if (connection->pool == NULL) 794 if (connection->pool == NULL)
790 { 795 {
791#if HAVE_MESSAGES 796 CONNECTION_CLOSE_ERROR (connection,
792 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n"); 797 "Failed to create memory pool!\n");
793#endif 798 return MHD_YES;
794 connection_close_error (connection);
795 return MHD_NO;
796 } 799 }
797 fd = connection->socket_fd; 800 fd = connection->socket_fd;
798 p->fd = fd; 801 p->fd = fd;
@@ -822,7 +825,8 @@ MHD_connection_get_pollfd (struct MHD_Connection *connection, struct MHD_Pollfd
822 if ((connection->read_closed) && 825 if ((connection->read_closed) &&
823 (connection->read_buffer_offset == 0)) 826 (connection->read_buffer_offset == 0))
824 { 827 {
825 connection->state = MHD_CONNECTION_CLOSED; 828 CONNECTION_CLOSE_ERROR (connection,
829 "Connection buffer to small for request\n");
826 continue; 830 continue;
827 } 831 }
828 if ((connection->read_buffer_offset == connection->read_buffer_size) 832 if ((connection->read_buffer_offset == connection->read_buffer_size)
@@ -883,7 +887,8 @@ MHD_connection_get_pollfd (struct MHD_Connection *connection, struct MHD_Pollfd
883 read buffer if needed, no size-check required */ 887 read buffer if needed, no size-check required */
884 if (MHD_YES == connection->read_closed) 888 if (MHD_YES == connection->read_closed)
885 { 889 {
886 connection->state = MHD_CONNECTION_CLOSED; 890 CONNECTION_CLOSE_ERROR (connection,
891 "Connection closed while reading request\n");
887 continue; 892 continue;
888 } 893 }
889 p->events |= MHD_POLL_ACTION_IN; 894 p->events |= MHD_POLL_ACTION_IN;
@@ -923,10 +928,7 @@ MHD_connection_get_pollfd (struct MHD_Connection *connection, struct MHD_Pollfd
923 EXTRA_CHECK (0); 928 EXTRA_CHECK (0);
924 break; 929 break;
925 case MHD_CONNECTION_CLOSED: 930 case MHD_CONNECTION_CLOSED:
926 if (connection->socket_fd != -1)
927 connection_close_error (connection);
928 return MHD_YES; /* do nothing, not even reading */ 931 return MHD_YES; /* do nothing, not even reading */
929
930 default: 932 default:
931 EXTRA_CHECK (0); 933 EXTRA_CHECK (0);
932 } 934 }
@@ -1227,11 +1229,8 @@ call_connection_handler (struct MHD_Connection *connection)
1227 &connection->client_context)) 1229 &connection->client_context))
1228 { 1230 {
1229 /* serious internal error, close connection */ 1231 /* serious internal error, close connection */
1230#if HAVE_MESSAGES 1232 CONNECTION_CLOSE_ERROR (connection,
1231 MHD_DLOG (connection->daemon, 1233 "Internal application error, closing connection.\n");
1232 "Internal application error, closing connection.\n");
1233#endif
1234 connection_close_error (connection);
1235 return; 1234 return;
1236 } 1235 }
1237} 1236}
@@ -1279,11 +1278,8 @@ process_request_body (struct MHD_Connection *connection)
1279 if (i == 0) 1278 if (i == 0)
1280 { 1279 {
1281 /* malformed encoding */ 1280 /* malformed encoding */
1282#if HAVE_MESSAGES 1281 CONNECTION_CLOSE_ERROR (connection,
1283 MHD_DLOG (connection->daemon, 1282 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1284 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1285#endif
1286 connection_close_error (connection);
1287 return; 1283 return;
1288 } 1284 }
1289 available -= i; 1285 available -= i;
@@ -1334,11 +1330,8 @@ process_request_body (struct MHD_Connection *connection)
1334 if (malformed) 1330 if (malformed)
1335 { 1331 {
1336 /* malformed encoding */ 1332 /* malformed encoding */
1337#if HAVE_MESSAGES 1333 CONNECTION_CLOSE_ERROR (connection,
1338 MHD_DLOG (connection->daemon, 1334 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1339 "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1340#endif
1341 connection_close_error (connection);
1342 return; 1335 return;
1343 } 1336 }
1344 i++; 1337 i++;
@@ -1390,11 +1383,8 @@ process_request_body (struct MHD_Connection *connection)
1390 &connection->client_context)) 1383 &connection->client_context))
1391 { 1384 {
1392 /* serious internal error, close connection */ 1385 /* serious internal error, close connection */
1393#if HAVE_MESSAGES 1386 CONNECTION_CLOSE_ERROR (connection,
1394 MHD_DLOG (connection->daemon, 1387 "Internal application error, closing connection.\n");
1395 "Internal application error, closing connection.\n");
1396#endif
1397 connection_close_error (connection);
1398 return; 1388 return;
1399 } 1389 }
1400 if (processed > used) 1390 if (processed > used)
@@ -1458,7 +1448,7 @@ do_read (struct MHD_Connection *connection)
1458 MHD_DLOG (connection->daemon, 1448 MHD_DLOG (connection->daemon,
1459 "Failed to receive data: %s\n", STRERROR (errno)); 1449 "Failed to receive data: %s\n", STRERROR (errno));
1460#endif 1450#endif
1461 connection_close_error (connection); 1451 CONNECTION_CLOSE_ERROR (connection, NULL);
1462 return MHD_YES; 1452 return MHD_YES;
1463 } 1453 }
1464 if (bytes_read == 0) 1454 if (bytes_read == 0)
@@ -1505,7 +1495,7 @@ do_write (struct MHD_Connection *connection)
1505 MHD_DLOG (connection->daemon, 1495 MHD_DLOG (connection->daemon,
1506 "Failed to send data: %s\n", STRERROR (errno)); 1496 "Failed to send data: %s\n", STRERROR (errno));
1507#endif 1497#endif
1508 connection_close_error (connection); 1498 CONNECTION_CLOSE_ERROR (connection, NULL);
1509 return MHD_YES; 1499 return MHD_YES;
1510 } 1500 }
1511#if DEBUG_SEND_DATA 1501#if DEBUG_SEND_DATA
@@ -1555,11 +1545,8 @@ process_header_line (struct MHD_Connection *connection, char *line)
1555 if (colon == NULL) 1545 if (colon == NULL)
1556 { 1546 {
1557 /* error in header line, die hard */ 1547 /* error in header line, die hard */
1558#if HAVE_MESSAGES 1548 CONNECTION_CLOSE_ERROR (connection,
1559 MHD_DLOG (connection->daemon, 1549 "Received malformed line (no colon), closing connection.\n");
1560 "Received malformed line (no colon), closing connection.\n");
1561#endif
1562 connection->state = MHD_CONNECTION_CLOSED;
1563 return MHD_NO; 1550 return MHD_NO;
1564 } 1551 }
1565 /* zero-terminate header */ 1552 /* zero-terminate header */
@@ -1696,7 +1683,7 @@ parse_connection_headers (struct MHD_Connection *connection)
1696 "Failed to parse `%s' header `%s', closing connection.\n", 1683 "Failed to parse `%s' header `%s', closing connection.\n",
1697 MHD_HTTP_HEADER_CONTENT_LENGTH, clen); 1684 MHD_HTTP_HEADER_CONTENT_LENGTH, clen);
1698#endif 1685#endif
1699 connection->state = MHD_CONNECTION_CLOSED; 1686 CONNECTION_CLOSE_ERROR (connection, NULL);
1700 return; 1687 return;
1701 } 1688 }
1702 connection->remaining_upload_size = cval; 1689 connection->remaining_upload_size = cval;
@@ -1726,15 +1713,15 @@ parse_connection_headers (struct MHD_Connection *connection)
1726 * implementations (multithreaded, external select, internal select) 1713 * implementations (multithreaded, external select, internal select)
1727 * call this function to handle reads. 1714 * call this function to handle reads.
1728 * 1715 *
1729 * @return MHD_YES if we should continue to process the 1716 * @return always MHD_YES (we should continue to process the
1730 * connection (not dead yet), MHD_NO if it died 1717 * connection)
1731 */ 1718 */
1732int 1719int
1733MHD_connection_handle_read (struct MHD_Connection *connection) 1720MHD_connection_handle_read (struct MHD_Connection *connection)
1734{ 1721{
1735 connection->last_activity = time (NULL); 1722 connection->last_activity = time (NULL);
1736 if (connection->state == MHD_CONNECTION_CLOSED) 1723 if (connection->state == MHD_CONNECTION_CLOSED)
1737 return MHD_NO; 1724 return MHD_YES;
1738 /* make sure "read" has a reasonable number of bytes 1725 /* make sure "read" has a reasonable number of bytes
1739 in buffer to use per system call (if possible) */ 1726 in buffer to use per system call (if possible) */
1740 if (connection->read_buffer_offset + MHD_BUF_INC_SIZE > 1727 if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
@@ -1767,9 +1754,7 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1767 } 1754 }
1768 break; 1755 break;
1769 case MHD_CONNECTION_CLOSED: 1756 case MHD_CONNECTION_CLOSED:
1770 if (connection->socket_fd != -1) 1757 return MHD_YES;
1771 connection_close_error (connection);
1772 return MHD_NO;
1773 default: 1758 default:
1774 /* shrink read buffer to how much is actually used */ 1759 /* shrink read buffer to how much is actually used */
1775 MHD_pool_reallocate (connection->pool, 1760 MHD_pool_reallocate (connection->pool,
@@ -1783,14 +1768,15 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1783 return MHD_YES; 1768 return MHD_YES;
1784} 1769}
1785 1770
1771
1786/** 1772/**
1787 * This function was created to handle writes to sockets when it has 1773 * This function was created to handle writes to sockets when it has
1788 * been determined that the socket can be written to. All 1774 * been determined that the socket can be written to. All
1789 * implementations (multithreaded, external select, internal select) 1775 * implementations (multithreaded, external select, internal select)
1790 * call this function 1776 * call this function
1791 * 1777 *
1792 * @return MHD_YES if we should continue to process the 1778 * @return always MHD_YES (we should continue to process the
1793 * connection (not dead yet), MHD_NO if it died 1779 * connection)
1794 */ 1780 */
1795int 1781int
1796MHD_connection_handle_write (struct MHD_Connection *connection) 1782MHD_connection_handle_write (struct MHD_Connection *connection)
@@ -1828,8 +1814,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1828 MHD_DLOG (connection->daemon, 1814 MHD_DLOG (connection->daemon,
1829 "Failed to send data: %s\n", STRERROR (errno)); 1815 "Failed to send data: %s\n", STRERROR (errno));
1830#endif 1816#endif
1831 connection_close_error (connection); 1817 CONNECTION_CLOSE_ERROR (connection, NULL);
1832 return MHD_NO; 1818 return MHD_YES;
1833 } 1819 }
1834#if DEBUG_SEND_DATA 1820#if DEBUG_SEND_DATA
1835 FPRINTF (stderr, 1821 FPRINTF (stderr,
@@ -1889,8 +1875,8 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1889 MHD_DLOG (connection->daemon, 1875 MHD_DLOG (connection->daemon,
1890 "Failed to send data: %s\n", STRERROR (errno)); 1876 "Failed to send data: %s\n", STRERROR (errno));
1891#endif 1877#endif
1892 connection_close_error (connection); 1878 CONNECTION_CLOSE_ERROR (connection, NULL);
1893 return MHD_NO; 1879 return MHD_YES;
1894 } 1880 }
1895 connection->response_write_position += ret; 1881 connection->response_write_position += ret;
1896 if (connection->response_write_position == 1882 if (connection->response_write_position ==
@@ -1920,16 +1906,14 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1920 EXTRA_CHECK (0); 1906 EXTRA_CHECK (0);
1921 break; 1907 break;
1922 case MHD_CONNECTION_CLOSED: 1908 case MHD_CONNECTION_CLOSED:
1923 if (connection->socket_fd != -1) 1909 return MHD_YES;
1924 connection_close_error (connection);
1925 return MHD_NO;
1926 case MHD_TLS_CONNECTION_INIT: 1910 case MHD_TLS_CONNECTION_INIT:
1927 EXTRA_CHECK (0); 1911 EXTRA_CHECK (0);
1928 break; 1912 break;
1929 default: 1913 default:
1930 EXTRA_CHECK (0); 1914 EXTRA_CHECK (0);
1931 connection_close_error (connection); 1915 CONNECTION_CLOSE_ERROR (connection, "Internal error\n");
1932 return MHD_NO; 1916 return MHD_YES;
1933 } 1917 }
1934 break; 1918 break;
1935 } 1919 }
@@ -1948,6 +1932,7 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1948int 1932int
1949MHD_connection_handle_idle (struct MHD_Connection *connection) 1933MHD_connection_handle_idle (struct MHD_Connection *connection)
1950{ 1934{
1935 struct MHD_Daemon *daemon;
1951 unsigned int timeout; 1936 unsigned int timeout;
1952 const char *end; 1937 const char *end;
1953 char *line; 1938 char *line;
@@ -1968,13 +1953,14 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
1968 continue; 1953 continue;
1969 if (connection->read_closed) 1954 if (connection->read_closed)
1970 { 1955 {
1971 connection->state = MHD_CONNECTION_CLOSED; 1956 CONNECTION_CLOSE_ERROR (connection,
1957 "Connection closed while reading request\n");
1972 continue; 1958 continue;
1973 } 1959 }
1974 break; 1960 break;
1975 } 1961 }
1976 if (MHD_NO == parse_initial_message_line (connection, line)) 1962 if (MHD_NO == parse_initial_message_line (connection, line))
1977 connection->state = MHD_CONNECTION_CLOSED; 1963 CONNECTION_CLOSE_ERROR (connection, NULL);
1978 else 1964 else
1979 connection->state = MHD_CONNECTION_URL_RECEIVED; 1965 connection->state = MHD_CONNECTION_URL_RECEIVED;
1980 continue; 1966 continue;
@@ -1986,7 +1972,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
1986 continue; 1972 continue;
1987 if (connection->read_closed) 1973 if (connection->read_closed)
1988 { 1974 {
1989 connection->state = MHD_CONNECTION_CLOSED; 1975 CONNECTION_CLOSE_ERROR (connection,
1976 "Connection closed while reading request\n");
1990 continue; 1977 continue;
1991 } 1978 }
1992 break; 1979 break;
@@ -2013,7 +2000,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2013 continue; 2000 continue;
2014 if (connection->read_closed) 2001 if (connection->read_closed)
2015 { 2002 {
2016 connection->state = MHD_CONNECTION_CLOSED; 2003 CONNECTION_CLOSE_ERROR (connection,
2004 "Connection closed while reading request\n");
2017 continue; 2005 continue;
2018 } 2006 }
2019 break; 2007 break;
@@ -2088,7 +2076,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2088 continue; 2076 continue;
2089 if (connection->read_closed) 2077 if (connection->read_closed)
2090 { 2078 {
2091 connection->state = MHD_CONNECTION_CLOSED; 2079 CONNECTION_CLOSE_ERROR (connection,
2080 "Connection closed while reading request\n");
2092 continue; 2081 continue;
2093 } 2082 }
2094 break; 2083 break;
@@ -2115,7 +2104,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2115 continue; 2104 continue;
2116 if (connection->read_closed) 2105 if (connection->read_closed)
2117 { 2106 {
2118 connection->state = MHD_CONNECTION_CLOSED; 2107 CONNECTION_CLOSE_ERROR (connection,
2108 "Connection closed while reading request\n");
2119 continue; 2109 continue;
2120 } 2110 }
2121 break; 2111 break;
@@ -2138,11 +2128,8 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2138 if (MHD_NO == build_header_response (connection)) 2128 if (MHD_NO == build_header_response (connection))
2139 { 2129 {
2140 /* oops - close! */ 2130 /* oops - close! */
2141#if HAVE_MESSAGES 2131 CONNECTION_CLOSE_ERROR (connection,
2142 MHD_DLOG (connection->daemon, 2132 "Closing connection (failed to create response header)\n");
2143 "Closing connection (failed to create response header)\n");
2144#endif
2145 connection->state = MHD_CONNECTION_CLOSED;
2146 continue; 2133 continue;
2147 } 2134 }
2148 connection->state = MHD_CONNECTION_HEADERS_SENDING; 2135 connection->state = MHD_CONNECTION_HEADERS_SENDING;
@@ -2253,7 +2240,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2253 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))) 2240 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
2254 { 2241 {
2255 /* http 1.0, version-less requests cannot be pipelined */ 2242 /* http 1.0, version-less requests cannot be pipelined */
2256 connection->state = MHD_CONNECTION_CLOSED; 2243 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_COMPLETED_OK);
2257 MHD_pool_destroy (connection->pool); 2244 MHD_pool_destroy (connection->pool);
2258 connection->pool = NULL; 2245 connection->pool = NULL;
2259 connection->read_buffer = NULL; 2246 connection->read_buffer = NULL;
@@ -2271,9 +2258,28 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2271 } 2258 }
2272 continue; 2259 continue;
2273 case MHD_CONNECTION_CLOSED: 2260 case MHD_CONNECTION_CLOSED:
2274 if (connection->socket_fd != -1) 2261 daemon = connection->daemon;
2275 connection_close_error (connection); 2262 DLL_remove (daemon->connections_head,
2276 break; 2263 daemon->connections_tail,
2264 connection);
2265 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
2266 {
2267#if HAVE_MESSAGES
2268 MHD_DLOG (daemon, "Failed to acquire cleanup mutex\n");
2269#endif
2270 abort();
2271 }
2272 DLL_insert (daemon->cleanup_head,
2273 daemon->cleanup_tail,
2274 connection);
2275 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
2276 {
2277#if HAVE_MESSAGES
2278 MHD_DLOG (daemon, "Failed to release cleanup mutex\n");
2279#endif
2280 abort();
2281 }
2282 return MHD_NO;
2277 default: 2283 default:
2278 EXTRA_CHECK (0); 2284 EXTRA_CHECK (0);
2279 break; 2285 break;
@@ -2281,12 +2287,11 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
2281 break; 2287 break;
2282 } 2288 }
2283 timeout = connection->daemon->connection_timeout; 2289 timeout = connection->daemon->connection_timeout;
2284 if ((connection->socket_fd != -1) && 2290 if ( (timeout != 0) &&
2285 (timeout != 0) && 2291 (timeout <= (time (NULL) - connection->last_activity)) )
2286 (timeout <= (time (NULL) - connection->last_activity)) )
2287 { 2292 {
2288 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); 2293 MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
2289 return MHD_NO; 2294 return MHD_YES;
2290 } 2295 }
2291 return MHD_YES; 2296 return MHD_YES;
2292} 2297}
diff --git a/src/daemon/connection_https.c b/src/daemon/connection_https.c
index 5487872e..e68ecbbe 100644
--- a/src/daemon/connection_https.c
+++ b/src/daemon/connection_https.c
@@ -33,23 +33,6 @@
33#include "reason_phrase.h" 33#include "reason_phrase.h"
34#include <gnutls/gnutls.h> 34#include <gnutls/gnutls.h>
35 35
36/**
37 * This function is called once a secure connection has been marked
38 * for closure.
39 *
40 * NOTE: Some code duplication with connection_close_error
41 * in connection.c
42 *
43 * @param connection: the connection to close
44 * @param termination_code: the termination code with which the notify completed callback function is called.
45 */
46static void
47MHD_tls_connection_close (struct MHD_Connection *connection,
48 enum MHD_RequestTerminationCode termination_code)
49{
50 gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR);
51 MHD_connection_close (connection, termination_code);
52}
53 36
54 37
55/** 38/**
@@ -65,9 +48,8 @@ MHD_tls_connection_close (struct MHD_Connection *connection,
65 * Application data is forwarded to the underlying daemon for 48 * Application data is forwarded to the underlying daemon for
66 * processing. 49 * processing.
67 * 50 *
68 * @param connection : the source connection 51 * @param connection the source connection
69 * @return MHD_YES if we should continue to process the 52 * @return always MHD_YES (we should continue to process the connection)
70 * connection (not dead yet), MHD_NO if it died
71 */ 53 */
72static int 54static int
73MHD_tls_connection_handle_read (struct MHD_Connection *connection) 55MHD_tls_connection_handle_read (struct MHD_Connection *connection)
@@ -95,9 +77,9 @@ MHD_tls_connection_handle_read (struct MHD_Connection *connection)
95 MHD_DLOG (connection->daemon, 77 MHD_DLOG (connection->daemon,
96 "Error: received handshake message out of context\n"); 78 "Error: received handshake message out of context\n");
97#endif 79#endif
98 MHD_tls_connection_close (connection, 80 MHD_connection_close (connection,
99 MHD_REQUEST_TERMINATED_WITH_ERROR); 81 MHD_REQUEST_TERMINATED_WITH_ERROR);
100 return MHD_NO; 82 return MHD_YES;
101 } 83 }
102 return MHD_connection_handle_read (connection); 84 return MHD_connection_handle_read (connection);
103} 85}
@@ -109,8 +91,7 @@ MHD_tls_connection_handle_read (struct MHD_Connection *connection)
109 * will forward all write requests to the underlying daemon unless 91 * will forward all write requests to the underlying daemon unless
110 * the connection has been marked for closing. 92 * the connection has been marked for closing.
111 * 93 *
112 * @return MHD_connection_handle_write() if we should continue to 94 * @return always MHD_YES (we should continue to process the connection)
113 * process the connection (not dead yet), MHD_NO if it died
114 */ 95 */
115static int 96static int
116MHD_tls_connection_handle_write (struct MHD_Connection *connection) 97MHD_tls_connection_handle_write (struct MHD_Connection *connection)
@@ -142,9 +123,9 @@ MHD_tls_connection_handle_write (struct MHD_Connection *connection)
142 MHD_DLOG (connection->daemon, 123 MHD_DLOG (connection->daemon,
143 "Error: received handshake message out of context\n"); 124 "Error: received handshake message out of context\n");
144#endif 125#endif
145 MHD_tls_connection_close (connection, 126 MHD_connection_close (connection,
146 MHD_REQUEST_TERMINATED_WITH_ERROR); 127 MHD_REQUEST_TERMINATED_WITH_ERROR);
147 return MHD_NO; 128 return MHD_YES;
148 } 129 }
149 return MHD_connection_handle_write (connection); 130 return MHD_connection_handle_write (connection);
150} 131}
@@ -170,13 +151,9 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
170 __FUNCTION__, MHD_state_to_string (connection->state)); 151 __FUNCTION__, MHD_state_to_string (connection->state));
171#endif 152#endif
172 timeout = connection->daemon->connection_timeout; 153 timeout = connection->daemon->connection_timeout;
173 if ((connection->socket_fd != -1) && (timeout != 0) 154 if ( (timeout != 0) && (time (NULL) - timeout > connection->last_activity))
174 && (time (NULL) - timeout > connection->last_activity)) 155 MHD_connection_close (connection,
175 { 156 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
176 MHD_tls_connection_close (connection,
177 MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
178 return MHD_NO;
179 }
180 switch (connection->state) 157 switch (connection->state)
181 { 158 {
182 /* on newly created connections we might reach here before any reply has been received */ 159 /* on newly created connections we might reach here before any reply has been received */
@@ -184,14 +161,12 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection)
184 return MHD_YES; 161 return MHD_YES;
185 /* close connection if necessary */ 162 /* close connection if necessary */
186 case MHD_CONNECTION_CLOSED: 163 case MHD_CONNECTION_CLOSED:
187 if (connection->socket_fd != -1) 164 gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR);
188 MHD_tls_connection_close (connection, 165 return MHD_connection_handle_idle (connection);
189 MHD_REQUEST_TERMINATED_COMPLETED_OK);
190 return MHD_NO;
191 default: 166 default:
192 if ( (0 != gnutls_record_check_pending (connection->tls_session)) && 167 if ( (0 != gnutls_record_check_pending (connection->tls_session)) &&
193 (MHD_YES != MHD_tls_connection_handle_read (connection)) ) 168 (MHD_YES != MHD_tls_connection_handle_read (connection)) )
194 return MHD_NO; 169 return MHD_YES;
195 return MHD_connection_handle_idle (connection); 170 return MHD_connection_handle_idle (connection);
196 } 171 }
197 return MHD_YES; 172 return MHD_YES;
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index 6c6144be..0fa51260 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -150,7 +150,7 @@ struct MHD_IPCount
150}; 150};
151 151
152/** 152/**
153 * Lock shared structure for IP connection counts 153 * Lock shared structure for IP connection counts and connection DLLs.
154 * 154 *
155 * @param daemon handle to daemon where lock is 155 * @param daemon handle to daemon where lock is
156 */ 156 */
@@ -167,7 +167,7 @@ MHD_ip_count_lock(struct MHD_Daemon *daemon)
167} 167}
168 168
169/** 169/**
170 * Unlock shared structure for IP connection counts 170 * Unlock shared structure for IP connection counts and connection DLLs.
171 * 171 *
172 * @param daemon handle to daemon where lock is 172 * @param daemon handle to daemon where lock is
173 */ 173 */
@@ -495,6 +495,7 @@ MHD_TLS_init (struct MHD_Daemon *daemon)
495} 495}
496#endif 496#endif
497 497
498
498/** 499/**
499 * Obtain the select sets for this daemon. 500 * Obtain the select sets for this daemon.
500 * 501 *
@@ -513,7 +514,8 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
513 fd_set * read_fd_set, 514 fd_set * read_fd_set,
514 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd) 515 fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
515{ 516{
516 struct MHD_Connection *con_itr; 517 struct MHD_Connection *pos;
518 struct MHD_Connection *next;
517 int fd; 519 int fd;
518 520
519 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL) 521 if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL)
@@ -528,15 +530,15 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
528 if ((*max_fd) < fd) 530 if ((*max_fd) < fd)
529 *max_fd = fd; 531 *max_fd = fd;
530 532
531 con_itr = daemon->connections; 533 next = daemon->connections_head;
532 while (con_itr != NULL) 534 while (NULL != (pos = next))
533 { 535 {
534 if (MHD_YES != MHD_connection_get_fdset (con_itr, 536 next = pos->next;
537 if (MHD_YES != MHD_connection_get_fdset (pos,
535 read_fd_set, 538 read_fd_set,
536 write_fd_set, 539 write_fd_set,
537 except_fd_set, max_fd)) 540 except_fd_set, max_fd))
538 return MHD_NO; 541 return MHD_NO;
539 con_itr = con_itr->next;
540 } 542 }
541#if DEBUG_CONNECT 543#if DEBUG_CONNECT
542 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd); 544 MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
@@ -572,7 +574,8 @@ MHD_handle_connection (void *data)
572#endif 574#endif
573 575
574 timeout = con->daemon->connection_timeout; 576 timeout = con->daemon->connection_timeout;
575 while ((!con->daemon->shutdown) && (con->socket_fd != -1)) { 577 while ( (!con->daemon->shutdown) && (con->state != MHD_CONNECTION_CLOSED) )
578 {
576 tvp = NULL; 579 tvp = NULL;
577 if (timeout > 0) 580 if (timeout > 0)
578 { 581 {
@@ -624,17 +627,19 @@ MHD_handle_connection (void *data)
624 break; 627 break;
625 } 628 }
626 /* call appropriate connection handler if necessary */ 629 /* call appropriate connection handler if necessary */
627 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &rs))) 630 if (FD_ISSET (con->socket_fd, &rs))
628 con->read_handler (con); 631 con->read_handler (con);
629 if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws))) 632 if (FD_ISSET (con->socket_fd, &ws))
630 con->write_handler (con); 633 con->write_handler (con);
631 if (con->socket_fd != -1) 634 if (MHD_NO == con->idle_handler (con))
632 con->idle_handler (con); 635 {
636 return NULL;
637 }
633 } 638 }
634#ifdef HAVE_POLL_H 639#ifdef HAVE_POLL_H
635 else 640 else
636 { 641 {
637 /* use poll */ 642 /* use poll */
638 memset(&mp, 0, sizeof (struct MHD_Pollfd)); 643 memset(&mp, 0, sizeof (struct MHD_Pollfd));
639 MHD_connection_get_pollfd(con, &mp); 644 MHD_connection_get_pollfd(con, &mp);
640 memset(&p, 0, sizeof (p)); 645 memset(&p, 0, sizeof (p));
@@ -666,21 +671,20 @@ MHD_handle_connection (void *data)
666#endif 671#endif
667 break; 672 break;
668 } 673 }
669 if ( (con->socket_fd != -1) && 674 if (0 != (p[0].revents & POLLIN))
670 (0 != (p[0].revents & POLLIN)) )
671 con->read_handler (con); 675 con->read_handler (con);
672 if ( (con->socket_fd != -1) && 676 if (0 != (p[0].revents & POLLOUT))
673 (0 != (p[0].revents & POLLOUT)) )
674 con->write_handler (con); 677 con->write_handler (con);
675 if (con->socket_fd != -1) 678 if (0 != (p[0].revents & (POLLERR | POLLHUP)))
676 con->idle_handler (con);
677 if ( (con->socket_fd != -1) &&
678 (0 != (p[0].revents & (POLLERR | POLLHUP))) )
679 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR); 679 MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
680 if (MHD_NO == con->idle_handler (con))
681 {
682 return NULL; /* "instant" termination, 'con' no longer valid! */
683 }
680 } 684 }
681#endif 685#endif
682 } 686 }
683 if (con->socket_fd != -1) 687 if (con->state != MHD_CONNECTION_IN_CLEANUP)
684 { 688 {
685#if DEBUG_CLOSE 689#if DEBUG_CLOSE
686#if HAVE_MESSAGES 690#if HAVE_MESSAGES
@@ -688,7 +692,9 @@ MHD_handle_connection (void *data)
688 "Processing thread terminating, closing connection\n"); 692 "Processing thread terminating, closing connection\n");
689#endif 693#endif
690#endif 694#endif
691 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN); 695 if (con->state != MHD_CONNECTION_CLOSED)
696 MHD_connection_close (con, MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
697 con->idle_handler (con);
692 } 698 }
693 return NULL; 699 return NULL;
694} 700}
@@ -706,8 +712,12 @@ recv_param_adapter (struct MHD_Connection *connection,
706 void *other, 712 void *other,
707 size_t i) 713 size_t i)
708{ 714{
709 if (connection->socket_fd == -1) 715 if ( (connection->socket_fd == -1) ||
710 return -1; 716 (connection->state == MHD_CONNECTION_CLOSED) )
717 {
718 errno = ENOTCONN;
719 return -1;
720 }
711 if (0 != (connection->daemon->options & MHD_USE_SSL)) 721 if (0 != (connection->daemon->options & MHD_USE_SSL))
712 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); 722 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
713 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); 723 return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL);
@@ -732,8 +742,12 @@ send_param_adapter (struct MHD_Connection *connection,
732 off_t left; 742 off_t left;
733 ssize_t ret; 743 ssize_t ret;
734#endif 744#endif
735 if (connection->socket_fd == -1) 745 if ( (connection->socket_fd == -1) ||
736 return -1; 746 (connection->state == MHD_CONNECTION_CLOSED) )
747 {
748 errno = ENOTCONN;
749 return -1;
750 }
737 if (0 != (connection->daemon->options & MHD_USE_SSL)) 751 if (0 != (connection->daemon->options & MHD_USE_SSL))
738 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL); 752 return SEND (connection->socket_fd, other, i, MSG_NOSIGNAL);
739#if LINUX 753#if LINUX
@@ -997,19 +1011,19 @@ MHD_add_connection (struct MHD_Daemon *daemon,
997 /* use non-blocking IO for gnutls */ 1011 /* use non-blocking IO for gnutls */
998 socket_set_nonblocking (connection->socket_fd); 1012 socket_set_nonblocking (connection->socket_fd);
999 } 1013 }
1000 switch (connection->daemon->cred_type) 1014 switch (daemon->cred_type)
1001 { 1015 {
1002 /* set needed credentials for certificate authentication. */ 1016 /* set needed credentials for certificate authentication. */
1003 case GNUTLS_CRD_CERTIFICATE: 1017 case GNUTLS_CRD_CERTIFICATE:
1004 gnutls_credentials_set (connection->tls_session, 1018 gnutls_credentials_set (connection->tls_session,
1005 GNUTLS_CRD_CERTIFICATE, 1019 GNUTLS_CRD_CERTIFICATE,
1006 connection->daemon->x509_cred); 1020 daemon->x509_cred);
1007 break; 1021 break;
1008 default: 1022 default:
1009#if HAVE_MESSAGES 1023#if HAVE_MESSAGES
1010 MHD_DLOG (connection->daemon, 1024 MHD_DLOG (connection->daemon,
1011 "Failed to setup TLS credentials: unknown credential type %d\n", 1025 "Failed to setup TLS credentials: unknown credential type %d\n",
1012 connection->daemon->cred_type); 1026 daemon->cred_type);
1013#endif 1027#endif
1014 SHUTDOWN (client_socket, SHUT_RDWR); 1028 SHUTDOWN (client_socket, SHUT_RDWR);
1015 CLOSE (client_socket); 1029 CLOSE (client_socket);
@@ -1059,8 +1073,10 @@ MHD_add_connection (struct MHD_Daemon *daemon,
1059 return MHD_NO; 1073 return MHD_NO;
1060 } 1074 }
1061 } 1075 }
1062 connection->next = daemon->connections; 1076 /* FIXME: race with removal operation! */
1063 daemon->connections = connection; 1077 DLL_insert (daemon->connections_head,
1078 daemon->connections_tail,
1079 connection);
1064 daemon->max_connections--; 1080 daemon->max_connections--;
1065 return MHD_YES; 1081 return MHD_YES;
1066} 1082}
@@ -1113,10 +1129,11 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1113 addr, addrlen); 1129 addr, addrlen);
1114} 1130}
1115 1131
1132
1116/** 1133/**
1117 * Free resources associated with all closed connections. 1134 * Free resources associated with all closed connections.
1118 * (destroy responses, free buffers, etc.). A connection 1135 * (destroy responses, free buffers, etc.). All closed
1119 * is known to be closed if the socket_fd is -1. 1136 * connections are kept in the "cleanup" doubly-linked list.
1120 * 1137 *
1121 * @param daemon daemon to clean up 1138 * @param daemon daemon to clean up
1122 */ 1139 */
@@ -1124,59 +1141,61 @@ static void
1124MHD_cleanup_connections (struct MHD_Daemon *daemon) 1141MHD_cleanup_connections (struct MHD_Daemon *daemon)
1125{ 1142{
1126 struct MHD_Connection *pos; 1143 struct MHD_Connection *pos;
1127 struct MHD_Connection *prev;
1128 void *unused; 1144 void *unused;
1129 int rc; 1145 int rc;
1130 1146
1131 pos = daemon->connections; 1147 if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
1132 prev = NULL;
1133 while (pos != NULL)
1134 { 1148 {
1135 if ((pos->socket_fd == -1) ||
1136 (((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1137 (daemon->shutdown) && (pos->socket_fd != -1))))
1138 {
1139 if (prev == NULL)
1140 daemon->connections = pos->next;
1141 else
1142 prev->next = pos->next;
1143 if (0 != (pos->daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1144 {
1145
1146 if (0 != (rc = pthread_join (pos->pid, &unused)))
1147 {
1148#if HAVE_MESSAGES 1149#if HAVE_MESSAGES
1149 MHD_DLOG (daemon, "Failed to join a thread: %s\n", 1150 MHD_DLOG (daemon, "Failed to acquire cleanup mutex\n");
1150 STRERROR (rc));
1151#endif
1152 abort();
1153 }
1154 }
1155 MHD_pool_destroy (pos->pool);
1156#if HTTPS_SUPPORT
1157 if (pos->tls_session != NULL)
1158 gnutls_deinit (pos->tls_session);
1159#endif 1151#endif
1160 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len); 1152 abort();
1161 if (pos->response != NULL) 1153 }
1154 while (NULL != (pos = daemon->cleanup_head))
1155 {
1156 DLL_remove (daemon->cleanup_head,
1157 daemon->cleanup_tail,
1158 pos);
1159 if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1160 (MHD_NO == pos->thread_joined) )
1161 {
1162 if (0 != (rc = pthread_join (pos->pid, &unused)))
1162 { 1163 {
1163 MHD_destroy_response (pos->response); 1164#if HAVE_MESSAGES
1164 pos->response = NULL; 1165 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
1166 STRERROR (rc));
1167#endif
1168 abort();
1165 } 1169 }
1166 free (pos->addr); 1170 }
1167 free (pos); 1171 MHD_pool_destroy (pos->pool);
1168 daemon->max_connections++; 1172#if HTTPS_SUPPORT
1169 if (prev == NULL) 1173 if (pos->tls_session != NULL)
1170 pos = daemon->connections; 1174 gnutls_deinit (pos->tls_session);
1171 else 1175#endif
1172 pos = prev->next; 1176 MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len);
1173 continue; 1177 if (pos->response != NULL)
1174 } 1178 {
1175 prev = pos; 1179 MHD_destroy_response (pos->response);
1176 pos = pos->next; 1180 pos->response = NULL;
1181 }
1182 if (-1 != pos->socket_fd)
1183 CLOSE (pos->socket_fd);
1184 if (NULL != pos->addr)
1185 free (pos->addr);
1186 free (pos);
1187 daemon->max_connections++;
1188 }
1189 if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
1190 {
1191#if HAVE_MESSAGES
1192 MHD_DLOG (daemon, "Failed to release cleanup mutex\n");
1193#endif
1194 abort();
1177 } 1195 }
1178} 1196}
1179 1197
1198
1180/** 1199/**
1181 * Obtain timeout value for select for this daemon 1200 * Obtain timeout value for select for this daemon
1182 * (only needed if connection timeout is used). The 1201 * (only needed if connection timeout is used). The
@@ -1201,7 +1220,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
1201 dto = daemon->connection_timeout; 1220 dto = daemon->connection_timeout;
1202 if (0 == dto) 1221 if (0 == dto)
1203 return MHD_NO; 1222 return MHD_NO;
1204 pos = daemon->connections; 1223 pos = daemon->connections_head;
1205 if (pos == NULL) 1224 if (pos == NULL)
1206 return MHD_NO; /* no connections */ 1225 return MHD_NO; /* no connections */
1207 now = time (NULL); 1226 now = time (NULL);
@@ -1238,6 +1257,7 @@ MHD_select (struct MHD_Daemon *daemon,
1238 int may_block) 1257 int may_block)
1239{ 1258{
1240 struct MHD_Connection *pos; 1259 struct MHD_Connection *pos;
1260 struct MHD_Connection *next;
1241 int num_ready; 1261 int num_ready;
1242 fd_set rs; 1262 fd_set rs;
1243 fd_set ws; 1263 fd_set ws;
@@ -1313,21 +1333,19 @@ MHD_select (struct MHD_Daemon *daemon,
1313 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 1333 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1314 { 1334 {
1315 /* do not have a thread per connection, process all connections now */ 1335 /* do not have a thread per connection, process all connections now */
1316 pos = daemon->connections; 1336 next = daemon->connections_head;
1317 while (pos != NULL) 1337 while (NULL != (pos = next))
1318 { 1338 {
1339 next = pos->next;
1319 ds = pos->socket_fd; 1340 ds = pos->socket_fd;
1320 if (ds != -1) 1341 if (ds != -1)
1321 { 1342 {
1322 /* TODO call con->read handler */
1323 if (FD_ISSET (ds, &rs)) 1343 if (FD_ISSET (ds, &rs))
1324 pos->read_handler (pos); 1344 pos->read_handler (pos);
1325 if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws))) 1345 if (FD_ISSET (ds, &ws))
1326 pos->write_handler (pos); 1346 pos->write_handler (pos);
1327 if (pos->socket_fd != -1) 1347 pos->idle_handler (pos);
1328 pos->idle_handler (pos);
1329 } 1348 }
1330 pos = pos->next;
1331 } 1349 }
1332 } 1350 }
1333 return MHD_YES; 1351 return MHD_YES;
@@ -1349,9 +1367,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1349{ 1367{
1350 unsigned int num_connections; 1368 unsigned int num_connections;
1351 struct MHD_Connection *pos; 1369 struct MHD_Connection *pos;
1370 struct MHD_Connection *next;
1352 1371
1353 num_connections = 0; 1372 num_connections = 0;
1354 pos = daemon->connections; 1373 pos = daemon->connections_head;
1355 while (pos != NULL) 1374 while (pos != NULL)
1356 { 1375 {
1357 num_connections++; 1376 num_connections++;
@@ -1385,7 +1404,7 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1385 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout; 1404 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
1386 1405
1387 i = 0; 1406 i = 0;
1388 pos = daemon->connections; 1407 pos = daemon->connections_head;
1389 while (pos != NULL) 1408 while (pos != NULL)
1390 { 1409 {
1391 memset(&mp, 0, sizeof (struct MHD_Pollfd)); 1410 memset(&mp, 0, sizeof (struct MHD_Pollfd));
@@ -1413,9 +1432,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1413 if (daemon->socket_fd < 0) 1432 if (daemon->socket_fd < 0)
1414 return MHD_YES; 1433 return MHD_YES;
1415 i = 0; 1434 i = 0;
1416 pos = daemon->connections; 1435 next = daemon->connections_head;
1417 while (pos != NULL) 1436 while (NULL != (pos = next))
1418 { 1437 {
1438 next = pos->next;
1419 /* first, sanity checks */ 1439 /* first, sanity checks */
1420 if (i >= num_connections) 1440 if (i >= num_connections)
1421 break; /* connection list changed somehow, retry later ... */ 1441 break; /* connection list changed somehow, retry later ... */
@@ -1427,11 +1447,9 @@ MHD_poll_all (struct MHD_Daemon *daemon,
1427 if (0 != (p[poll_server+i].revents & POLLIN)) 1447 if (0 != (p[poll_server+i].revents & POLLIN))
1428 pos->read_handler (pos); 1448 pos->read_handler (pos);
1429 if (0 != (p[poll_server+i].revents & POLLOUT)) 1449 if (0 != (p[poll_server+i].revents & POLLOUT))
1430 pos->write_handler (pos); 1450 pos->write_handler (pos);
1431 if (pos->socket_fd != -1) 1451 pos->idle_handler (pos);
1432 pos->idle_handler (pos);
1433 i++; 1452 i++;
1434 pos = pos->next;
1435 } 1453 }
1436 if ( (1 == poll_server) && 1454 if ( (1 == poll_server) &&
1437 (0 != (p[0].revents & POLLIN)) ) 1455 (0 != (p[0].revents & POLLIN)) )
@@ -1729,18 +1747,22 @@ parse_options_va (struct MHD_Daemon *daemon,
1729 daemon->cred_type = va_arg (ap, gnutls_credentials_type_t); 1747 daemon->cred_type = va_arg (ap, gnutls_credentials_type_t);
1730 break; 1748 break;
1731 case MHD_OPTION_HTTPS_PRIORITIES: 1749 case MHD_OPTION_HTTPS_PRIORITIES:
1732 ret = gnutls_priority_init (&daemon->priority_cache, 1750 if (daemon->options & MHD_USE_SSL)
1733 pstr = va_arg (ap, const char*), 1751 {
1734 NULL); 1752 gnutls_priority_deinit (daemon->priority_cache);
1753 ret = gnutls_priority_init (&daemon->priority_cache,
1754 pstr = va_arg (ap, const char*),
1755 NULL);
1735#if HAVE_MESSAGES 1756#if HAVE_MESSAGES
1736 if (ret != GNUTLS_E_SUCCESS) 1757 if (ret != GNUTLS_E_SUCCESS)
1737 FPRINTF (stderr, 1758 FPRINTF (stderr,
1738 "Setting priorities to `%s' failed: %s\n", 1759 "Setting priorities to `%s' failed: %s\n",
1739 pstr, 1760 pstr,
1740 gnutls_strerror (ret)); 1761 gnutls_strerror (ret));
1741#endif 1762#endif
1742 if (ret != GNUTLS_E_SUCCESS) 1763 if (ret != GNUTLS_E_SUCCESS)
1743 return MHD_NO; 1764 return MHD_NO;
1765 }
1744 break; 1766 break;
1745#endif 1767#endif
1746#ifdef DAUTH_SUPPORT 1768#ifdef DAUTH_SUPPORT
@@ -2174,6 +2196,16 @@ MHD_start_daemon_va (unsigned int options,
2174 CLOSE (socket_fd); 2196 CLOSE (socket_fd);
2175 goto free_and_fail; 2197 goto free_and_fail;
2176 } 2198 }
2199 if (0 != pthread_mutex_init (&retVal->cleanup_connection_mutex, NULL))
2200 {
2201#if HAVE_MESSAGES
2202 MHD_DLOG (retVal,
2203 "MHD failed to initialize IP connection limit mutex\n");
2204#endif
2205 pthread_mutex_destroy (&retVal->cleanup_connection_mutex);
2206 CLOSE (socket_fd);
2207 goto free_and_fail;
2208 }
2177 2209
2178#if HTTPS_SUPPORT 2210#if HTTPS_SUPPORT
2179 /* initialize HTTPS daemon certificate aspects & send / recv functions */ 2211 /* initialize HTTPS daemon certificate aspects & send / recv functions */
@@ -2184,6 +2216,7 @@ MHD_start_daemon_va (unsigned int options,
2184 "Failed to initialize TLS support\n"); 2216 "Failed to initialize TLS support\n");
2185#endif 2217#endif
2186 CLOSE (socket_fd); 2218 CLOSE (socket_fd);
2219 pthread_mutex_destroy (&retVal->cleanup_connection_mutex);
2187 pthread_mutex_destroy (&retVal->per_ip_connection_mutex); 2220 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
2188 goto free_and_fail; 2221 goto free_and_fail;
2189 } 2222 }
@@ -2199,6 +2232,7 @@ MHD_start_daemon_va (unsigned int options,
2199 "Failed to create listen thread: %s\n", 2232 "Failed to create listen thread: %s\n",
2200 STRERROR (res_thread_create)); 2233 STRERROR (res_thread_create));
2201#endif 2234#endif
2235 pthread_mutex_destroy (&retVal->cleanup_connection_mutex);
2202 pthread_mutex_destroy (&retVal->per_ip_connection_mutex); 2236 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
2203 CLOSE (socket_fd); 2237 CLOSE (socket_fd);
2204 goto free_and_fail; 2238 goto free_and_fail;
@@ -2292,6 +2326,7 @@ thread_failed:
2292 if (i == 0) 2326 if (i == 0)
2293 { 2327 {
2294 CLOSE (socket_fd); 2328 CLOSE (socket_fd);
2329 pthread_mutex_destroy (&retVal->cleanup_connection_mutex);
2295 pthread_mutex_destroy (&retVal->per_ip_connection_mutex); 2330 pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
2296 if (NULL != retVal->worker_pool) 2331 if (NULL != retVal->worker_pool)
2297 free (retVal->worker_pool); 2332 free (retVal->worker_pool);
@@ -2319,27 +2354,45 @@ thread_failed:
2319 2354
2320 2355
2321/** 2356/**
2322 * Close all connections for the daemon 2357 * Close all connections for the daemon; must only be called after
2358 * all of the threads have been joined and there is no more concurrent
2359 * activity on the connection lists.
2323 * 2360 *
2324 * @param daemon daemon to close down 2361 * @param daemon daemon to close down
2325 */ 2362 */
2326static void 2363static void
2327MHD_close_connections (struct MHD_Daemon *daemon) 2364close_all_connections (struct MHD_Daemon *daemon)
2328{ 2365{
2329 while (daemon->connections != NULL) 2366 struct MHD_Connection *pos;
2367 void *unused;
2368 int rc;
2369
2370 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2330 { 2371 {
2331 if (-1 != daemon->connections->socket_fd) 2372 while (NULL != (pos = daemon->connections_head))
2332 { 2373 {
2333#if DEBUG_CLOSE 2374 if (0 != (rc = pthread_join (pos->pid, &unused)))
2375 {
2334#if HAVE_MESSAGES 2376#if HAVE_MESSAGES
2335 MHD_DLOG (daemon, "MHD shutdown, closing active connections\n"); 2377 MHD_DLOG (daemon, "Failed to join a thread: %s\n",
2378 STRERROR (rc));
2336#endif 2379#endif
2337#endif 2380 abort();
2338 MHD_connection_close (daemon->connections, 2381 }
2339 MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN); 2382 pos->thread_joined = MHD_YES;
2340 } 2383 }
2341 MHD_cleanup_connections (daemon);
2342 } 2384 }
2385 while (NULL != (pos = daemon->connections_head))
2386 {
2387 pos->state = MHD_CONNECTION_CLOSED;
2388 DLL_remove (daemon->connections_head,
2389 daemon->connections_tail,
2390 pos);
2391 DLL_insert (daemon->cleanup_head,
2392 daemon->cleanup_tail,
2393 pos);
2394 }
2395 MHD_cleanup_connections (daemon);
2343} 2396}
2344 2397
2345 2398
@@ -2387,7 +2440,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2387#endif 2440#endif
2388 abort(); 2441 abort();
2389 } 2442 }
2390 MHD_close_connections (&daemon->worker_pool[i]); 2443 close_all_connections (&daemon->worker_pool[i]);
2391 } 2444 }
2392 free (daemon->worker_pool); 2445 free (daemon->worker_pool);
2393 2446
@@ -2404,7 +2457,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2404 abort(); 2457 abort();
2405 } 2458 }
2406 } 2459 }
2407 MHD_close_connections (daemon); 2460 close_all_connections (daemon);
2408 CLOSE (fd); 2461 CLOSE (fd);
2409 2462
2410 /* TLS clean up */ 2463 /* TLS clean up */
@@ -2437,7 +2490,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
2437 pthread_mutex_destroy (&daemon->nnc_lock); 2490 pthread_mutex_destroy (&daemon->nnc_lock);
2438#endif 2491#endif
2439 pthread_mutex_destroy (&daemon->per_ip_connection_mutex); 2492 pthread_mutex_destroy (&daemon->per_ip_connection_mutex);
2440 2493 pthread_mutex_destroy (&daemon->cleanup_connection_mutex);
2441 free (daemon); 2494 free (daemon);
2442} 2495}
2443 2496
diff --git a/src/daemon/internal.h b/src/daemon/internal.h
index 9a3eb8cb..fcacc523 100644
--- a/src/daemon/internal.h
+++ b/src/daemon/internal.h
@@ -379,11 +379,15 @@ enum MHD_CONNECTION_STATE
379 MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1, 379 MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,
380 380
381 /** 381 /**
382 * 19: This connection is closed (no more activity 382 * 19: This connection is to be closed.
383 * allowed).
384 */ 383 */
385 MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1, 384 MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,
386 385
386 /**
387 * 20: This connection is finished (only to be freed)
388 */
389 MHD_CONNECTION_IN_CLEANUP = MHD_CONNECTION_CLOSED + 1,
390
387 /* 391 /*
388 * SSL/TLS connection states 392 * SSL/TLS connection states
389 */ 393 */
@@ -440,11 +444,16 @@ struct MHD_Connection
440{ 444{
441 445
442 /** 446 /**
443 * This is a linked list. 447 * This is a doubly-linked list.
444 */ 448 */
445 struct MHD_Connection *next; 449 struct MHD_Connection *next;
446 450
447 /** 451 /**
452 * This is a doubly-linked list.
453 */
454 struct MHD_Connection *prev;
455
456 /**
448 * Reference to the MHD_Daemon struct. 457 * Reference to the MHD_Daemon struct.
449 */ 458 */
450 struct MHD_Daemon *daemon; 459 struct MHD_Daemon *daemon;
@@ -622,6 +631,11 @@ struct MHD_Connection
622 int read_closed; 631 int read_closed;
623 632
624 /** 633 /**
634 * Set to MHD_YES if the thread has been joined.
635 */
636 int thread_joined;
637
638 /**
625 * State in the FSM for this connection. 639 * State in the FSM for this connection.
626 */ 640 */
627 enum MHD_CONNECTION_STATE state; 641 enum MHD_CONNECTION_STATE state;
@@ -747,9 +761,24 @@ struct MHD_Daemon
747 void *default_handler_cls; 761 void *default_handler_cls;
748 762
749 /** 763 /**
750 * Linked list of our current connections. 764 * Tail of doubly-linked list of our current, active connections.
765 */
766 struct MHD_Connection *connections_head;
767
768 /**
769 * Tail of doubly-linked list of our current, active connections.
770 */
771 struct MHD_Connection *connections_tail;
772
773 /**
774 * Tail of doubly-linked list of connections to clean up.
751 */ 775 */
752 struct MHD_Connection *connections; 776 struct MHD_Connection *cleanup_head;
777
778 /**
779 * Tail of doubly-linked list of connections to clean up.
780 */
781 struct MHD_Connection *cleanup_tail;
753 782
754 /** 783 /**
755 * Function to call to check if we should 784 * Function to call to check if we should
@@ -847,11 +876,16 @@ struct MHD_Daemon
847 pthread_t pid; 876 pthread_t pid;
848 877
849 /** 878 /**
850 * Mutex for per-IP connection counts 879 * Mutex for per-IP connection counts.
851 */ 880 */
852 pthread_mutex_t per_ip_connection_mutex; 881 pthread_mutex_t per_ip_connection_mutex;
853 882
854 /** 883 /**
884 * Mutex for (modifying) access to the "cleanup" connection DLL.
885 */
886 pthread_mutex_t cleanup_connection_mutex;
887
888 /**
855 * Listen socket. 889 * Listen socket.
856 */ 890 */
857 int socket_fd; 891 int socket_fd;
@@ -966,5 +1000,44 @@ struct MHD_Daemon
966#endif 1000#endif
967 1001
968 1002
1003/**
1004 * Insert an element at the head of a DLL. Assumes that head, tail and
1005 * element are structs with prev and next fields.
1006 *
1007 * @param head pointer to the head of the DLL
1008 * @param tail pointer to the tail of the DLL
1009 * @param element element to insert
1010 */
1011#define DLL_insert(head,tail,element) do { \
1012 (element)->next = (head); \
1013 (element)->prev = NULL; \
1014 if ((tail) == NULL) \
1015 (tail) = element; \
1016 else \
1017 (head)->prev = element; \
1018 (head) = (element); } while (0)
1019
1020
1021/**
1022 * Remove an element from a DLL. Assumes
1023 * that head, tail and element are structs
1024 * with prev and next fields.
1025 *
1026 * @param head pointer to the head of the DLL
1027 * @param tail pointer to the tail of the DLL
1028 * @param element element to remove
1029 */
1030#define DLL_remove(head,tail,element) do { \
1031 if ((element)->prev == NULL) \
1032 (head) = (element)->next; \
1033 else \
1034 (element)->prev->next = (element)->next; \
1035 if ((element)->next == NULL) \
1036 (tail) = (element)->prev; \
1037 else \
1038 (element)->next->prev = (element)->prev; \
1039 (element)->next = NULL; \
1040 (element)->prev = NULL; } while (0)
1041
969 1042
970#endif 1043#endif