aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-09-04 11:11:43 +0000
committerChristian Grothoff <christian@grothoff.org>2016-09-04 11:11:43 +0000
commite379ceb7df948e09982db6b1e7a9d7b4ffb722ae (patch)
treef18d2aa19ffda04c8a0ec203374adeb59e9973ae
parent7e9ec3e5306d96febf581a46992768f1400d2a25 (diff)
downloadlibmicrohttpd-e379ceb7df948e09982db6b1e7a9d7b4ffb722ae.tar.gz
libmicrohttpd-e379ceb7df948e09982db6b1e7a9d7b4ffb722ae.zip
-extend test to cover poll and epoll, epoll-related fixes
-rw-r--r--src/microhttpd/daemon.c85
-rw-r--r--src/microhttpd/test_upgrade_ssl.c13
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
395static int 395static int
396test_upgrade_internal_select () 396test_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",