diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 289 |
1 files changed, 171 insertions, 118 deletions
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 | |||
1124 | MHD_cleanup_connections (struct MHD_Daemon *daemon) | 1141 | MHD_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 | */ |
2326 | static void | 2363 | static void |
2327 | MHD_close_connections (struct MHD_Daemon *daemon) | 2364 | close_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 | ||