diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-09-04 11:11:43 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-09-04 11:11:43 +0000 |
commit | e379ceb7df948e09982db6b1e7a9d7b4ffb722ae (patch) | |
tree | f18d2aa19ffda04c8a0ec203374adeb59e9973ae | |
parent | 7e9ec3e5306d96febf581a46992768f1400d2a25 (diff) | |
download | libmicrohttpd-e379ceb7df948e09982db6b1e7a9d7b4ffb722ae.tar.gz libmicrohttpd-e379ceb7df948e09982db6b1e7a9d7b4ffb722ae.zip |
-extend test to cover poll and epoll, epoll-related fixes
-rw-r--r-- | src/microhttpd/daemon.c | 85 | ||||
-rw-r--r-- | src/microhttpd/test_upgrade_ssl.c | 13 |
2 files changed, 19 insertions, 79 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 08709c80..487575e0 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -3173,8 +3173,6 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon) | |||
3173 | { | 3173 | { |
3174 | struct UpgradeEpollHandle *ueh = events[i].data.ptr; | 3174 | struct UpgradeEpollHandle *ueh = events[i].data.ptr; |
3175 | struct MHD_UpgradeResponseHandle *urh = ueh->urh; | 3175 | struct MHD_UpgradeResponseHandle *urh = ueh->urh; |
3176 | struct epoll_event event; | ||
3177 | int fd; | ||
3178 | 3176 | ||
3179 | /* Update our state based on what is ready according to epoll() */ | 3177 | /* Update our state based on what is ready according to epoll() */ |
3180 | if (0 != (events[i].events & EPOLLIN)) | 3178 | if (0 != (events[i].events & EPOLLIN)) |
@@ -3184,79 +3182,6 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon) | |||
3184 | 3182 | ||
3185 | /* shuffle data based on buffers and FD readyness */ | 3183 | /* shuffle data based on buffers and FD readyness */ |
3186 | process_urh (urh); | 3184 | process_urh (urh); |
3187 | |||
3188 | /* if we drained the IO buffer, re-add to epoll() to wait for more! */ | ||
3189 | if (0 == (ueh->celi & MHD_EPOLL_STATE_READ_READY)) | ||
3190 | { | ||
3191 | event.events = EPOLLIN; | ||
3192 | event.data.ptr = ueh; | ||
3193 | fd = (ueh == &urh->mhd) ? ueh->socket : urh->connection->socket_fd; | ||
3194 | if (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
3195 | EPOLL_CTL_ADD, | ||
3196 | fd, | ||
3197 | &event)) | ||
3198 | { | ||
3199 | MHD_socket myfd; | ||
3200 | |||
3201 | /* Handle error by closing OUR socket; with some | ||
3202 | luck, this should tricker the application to fail | ||
3203 | to read, and then the application should close | ||
3204 | the connection completely. */ | ||
3205 | |||
3206 | /* epoll documentation suggests that closing a FD | ||
3207 | automatically removes it from the epoll set; | ||
3208 | however, this is not true as if we fail to do | ||
3209 | manually remove it, we are still seeing an event | ||
3210 | for this fd in epoll, causing grief | ||
3211 | (use-after-free...) --- at least on my system. */ | ||
3212 | myfd = urh->mhd.socket; | ||
3213 | if ( (fd != myfd) && | ||
3214 | (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
3215 | EPOLL_CTL_DEL, | ||
3216 | urh->mhd.socket, | ||
3217 | NULL)) ) | ||
3218 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | ||
3219 | urh->mhd.socket = MHD_INVALID_SOCKET; | ||
3220 | MHD_socket_close_ (myfd); | ||
3221 | continue; | ||
3222 | } | ||
3223 | } | ||
3224 | if (0 == (ueh->celi & MHD_EPOLL_STATE_WRITE_READY)) | ||
3225 | { | ||
3226 | event.events = EPOLLOUT; | ||
3227 | event.data.ptr = ueh; | ||
3228 | fd = (ueh == &ueh->urh->mhd) ? ueh->socket : ueh->urh->connection->socket_fd; | ||
3229 | if (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
3230 | EPOLL_CTL_ADD, | ||
3231 | fd, | ||
3232 | &event)) | ||
3233 | { | ||
3234 | MHD_socket myfd; | ||
3235 | |||
3236 | /* Handle error by closing OUR socket; with some | ||
3237 | luck, this should tricker the application to fail | ||
3238 | to read, and then the application should close | ||
3239 | the connection completely. */ | ||
3240 | |||
3241 | /* epoll documentation suggests that closing a FD | ||
3242 | automatically removes it from the epoll set; | ||
3243 | however, this is not true as if we fail to do | ||
3244 | manually remove it, we are still seeing an event | ||
3245 | for this fd in epoll, causing grief | ||
3246 | (use-after-free...) --- at least on my system. */ | ||
3247 | myfd = urh->mhd.socket; | ||
3248 | if ( (fd != myfd) && | ||
3249 | (0 != epoll_ctl (daemon->epoll_upgrade_fd, | ||
3250 | EPOLL_CTL_DEL, | ||
3251 | urh->mhd.socket, | ||
3252 | NULL)) ) | ||
3253 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | ||
3254 | |||
3255 | urh->mhd.socket = MHD_INVALID_SOCKET; | ||
3256 | MHD_socket_close_ (myfd); | ||
3257 | continue; | ||
3258 | } | ||
3259 | } | ||
3260 | } | 3185 | } |
3261 | } | 3186 | } |
3262 | return MHD_YES; | 3187 | return MHD_YES; |
@@ -3399,7 +3324,6 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
3399 | { | 3324 | { |
3400 | /* activity on an upgraded connection, we process | 3325 | /* activity on an upgraded connection, we process |
3401 | those in a separate epoll() */ | 3326 | those in a separate epoll() */ |
3402 | daemon->upgrade_fd_in_epoll = MHD_NO; | ||
3403 | run_epoll_for_upgrade (daemon); | 3327 | run_epoll_for_upgrade (daemon); |
3404 | continue; | 3328 | continue; |
3405 | } | 3329 | } |
@@ -4977,6 +4901,15 @@ thread_failed: | |||
4977 | /* clean up basic memory state in 'daemon' and return NULL to | 4901 | /* clean up basic memory state in 'daemon' and return NULL to |
4978 | indicate failure */ | 4902 | indicate failure */ |
4979 | #ifdef EPOLL_SUPPORT | 4903 | #ifdef EPOLL_SUPPORT |
4904 | if (MHD_YES == daemon->upgrade_fd_in_epoll) | ||
4905 | { | ||
4906 | if (0 != epoll_ctl (daemon->epoll_fd, | ||
4907 | EPOLL_CTL_DEL, | ||
4908 | daemon->epoll_upgrade_fd, | ||
4909 | NULL)) | ||
4910 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | ||
4911 | daemon->upgrade_fd_in_epoll = MHD_NO; | ||
4912 | } | ||
4980 | if (-1 != daemon->epoll_fd) | 4913 | if (-1 != daemon->epoll_fd) |
4981 | close (daemon->epoll_fd); | 4914 | close (daemon->epoll_fd); |
4982 | #if HTTPS_SUPPORT | 4915 | #if HTTPS_SUPPORT |
diff --git a/src/microhttpd/test_upgrade_ssl.c b/src/microhttpd/test_upgrade_ssl.c index fc8d55a6..ad5b40c5 100644 --- a/src/microhttpd/test_upgrade_ssl.c +++ b/src/microhttpd/test_upgrade_ssl.c | |||
@@ -393,13 +393,13 @@ ahc_upgrade (void *cls, | |||
393 | 393 | ||
394 | 394 | ||
395 | static int | 395 | static int |
396 | test_upgrade_internal_select () | 396 | test_upgrade_internal (int flags) |
397 | { | 397 | { |
398 | struct MHD_Daemon *d; | 398 | struct MHD_Daemon *d; |
399 | MHD_socket sock; | 399 | MHD_socket sock; |
400 | pid_t pid; | 400 | pid_t pid; |
401 | 401 | ||
402 | d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME | MHD_USE_TLS, | 402 | d = MHD_start_daemon (flags | MHD_USE_DEBUG | MHD_USE_SUSPEND_RESUME | MHD_USE_TLS, |
403 | 1080, | 403 | 1080, |
404 | NULL, NULL, | 404 | NULL, NULL, |
405 | &ahc_upgrade, NULL, | 405 | &ahc_upgrade, NULL, |
@@ -440,7 +440,14 @@ main (int argc, | |||
440 | 440 | ||
441 | if (0 != system ("openssl version 1> /dev/null")) | 441 | if (0 != system ("openssl version 1> /dev/null")) |
442 | return 77; /* openssl not available, can't run the test */ | 442 | return 77; /* openssl not available, can't run the test */ |
443 | errorCount += test_upgrade_internal_select (); | 443 | errorCount += test_upgrade_internal (MHD_USE_SELECT_INTERNALLY); |
444 | #ifdef HAVE_POLL | ||
445 | errorCount += test_upgrade_internal (MHD_USE_POLL_INTERNALLY); | ||
446 | #endif | ||
447 | #ifdef EPOLL_SUPPORT | ||
448 | errorCount += test_upgrade_internal (MHD_USE_EPOLL_INTERNALLY | | ||
449 | MHD_USE_TLS_EPOLL_UPGRADE); | ||
450 | #endif | ||
444 | if (errorCount != 0) | 451 | if (errorCount != 0) |
445 | fprintf (stderr, | 452 | fprintf (stderr, |
446 | "Error (code: %u)\n", | 453 | "Error (code: %u)\n", |