aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-03-20 08:22:58 +0000
committerChristian Grothoff <christian@grothoff.org>2011-03-20 08:22:58 +0000
commit2d15eceddf5b213e4c21137a12f267fee0e1c775 (patch)
treefc4217d395bc0bf628d75197fe24e11fb5e40873
parent52cc71a8bc50ac773eb220b8fda88fe44fb1d322 (diff)
downloadlibmicrohttpd-2d15eceddf5b213e4c21137a12f267fee0e1c775.tar.gz
libmicrohttpd-2d15eceddf5b213e4c21137a12f267fee0e1c775.zip
preliminary patch to poll race
-rw-r--r--ChangeLog4
-rw-r--r--src/daemon/daemon.c119
2 files changed, 103 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 2eab80e4..9e8b8f52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
1Sun Mar 20 09:16:53 CET 2011
2 Fixing race when using MHD_USE_THREAD_PER_CONNECTION in combination
3 with MHD_USE_POLL. -CG
4
1Fri Mar 18 13:23:47 CET 2011 5Fri Mar 18 13:23:47 CET 2011
2 Removing MSG_DONTWAIT which should not be needed and was presumably 6 Removing MSG_DONTWAIT which should not be needed and was presumably
3 causing problems with EAGAIN under certain circumstances. -ES 7 causing problems with EAGAIN under certain circumstances. -ES
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c
index e050d585..b85c8510 100644
--- a/src/daemon/daemon.c
+++ b/src/daemon/daemon.c
@@ -1333,18 +1333,19 @@ MHD_select (struct MHD_Daemon *daemon,
1333} 1333}
1334 1334
1335 1335
1336#ifdef HAVE_POLL_H
1336/** 1337/**
1337 * Poll for new connection. 1338 * Process all of our connections and possibly the server
1339 * socket using 'poll'.
1338 * 1340 *
1339 * @param daemon daemon to run poll loop for 1341 * @param daemon daemon to run poll loop for
1340 * @param may_block YES if blocking, NO if non-blocking 1342 * @param may_block YES if blocking, NO if non-blocking
1341 * @return MHD_NO on serious errors, MHD_YES on success 1343 * @return MHD_NO on serious errors, MHD_YES on success
1342 */ 1344 */
1343static int 1345static int
1344MHD_poll (struct MHD_Daemon *daemon, 1346MHD_poll_all (struct MHD_Daemon *daemon,
1345 int may_block) 1347 int may_block)
1346{ 1348{
1347#ifdef HAVE_POLL_H
1348 unsigned int num_connections; 1349 unsigned int num_connections;
1349 struct MHD_Connection *pos; 1350 struct MHD_Connection *pos;
1350 1351
@@ -1361,11 +1362,20 @@ MHD_poll (struct MHD_Daemon *daemon,
1361 unsigned MHD_LONG_LONG ltimeout; 1362 unsigned MHD_LONG_LONG ltimeout;
1362 unsigned int i; 1363 unsigned int i;
1363 int timeout; 1364 int timeout;
1365 unsigned int poll_server;
1364 1366
1365 memset (p, 0, sizeof (p)); 1367 memset (p, 0, sizeof (p));
1366 p[0].fd = daemon->socket_fd; 1368 if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) )
1367 p[0].events = POLLIN; 1369 {
1368 p[0].revents = 0; 1370 poll_server = 1;
1371 p[0].fd = daemon->socket_fd;
1372 p[0].events = POLLIN;
1373 p[0].revents = 0;
1374 }
1375 else
1376 {
1377 poll_server = 0;
1378 }
1369 if (may_block == MHD_NO) 1379 if (may_block == MHD_NO)
1370 timeout = 0; 1380 timeout = 0;
1371 else if (MHD_YES != MHD_get_timeout (daemon, &ltimeout)) 1381 else if (MHD_YES != MHD_get_timeout (daemon, &ltimeout))
@@ -1379,22 +1389,23 @@ MHD_poll (struct MHD_Daemon *daemon,
1379 { 1389 {
1380 memset(&mp, 0, sizeof (struct MHD_Pollfd)); 1390 memset(&mp, 0, sizeof (struct MHD_Pollfd));
1381 MHD_connection_get_pollfd (pos, &mp); 1391 MHD_connection_get_pollfd (pos, &mp);
1382 p[1+i].fd = mp.fd; 1392 p[poll_server+i].fd = mp.fd;
1383 if (mp.events & MHD_POLL_ACTION_IN) 1393 if (mp.events & MHD_POLL_ACTION_IN)
1384 p[1+i].events |= POLLIN; 1394 p[poll_server+i].events |= POLLIN;
1385 if (mp.events & MHD_POLL_ACTION_OUT) 1395 if (mp.events & MHD_POLL_ACTION_OUT)
1386 p[1+i].events |= POLLOUT; 1396 p[poll_server+i].events |= POLLOUT;
1387 i++; 1397 i++;
1388 pos = pos->next; 1398 pos = pos->next;
1389 } 1399 }
1390 if (poll (p, 1 + num_connections, timeout) < 0) { 1400 if (poll (p, poll_server + num_connections, timeout) < 0)
1391 if (errno == EINTR) 1401 {
1392 return MHD_YES; 1402 if (errno == EINTR)
1403 return MHD_YES;
1393#if HAVE_MESSAGES 1404#if HAVE_MESSAGES
1394 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); 1405 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
1395#endif 1406#endif
1396 return MHD_NO; 1407 return MHD_NO;
1397 } 1408 }
1398 /* handle shutdown cases */ 1409 /* handle shutdown cases */
1399 if (daemon->shutdown == MHD_YES) 1410 if (daemon->shutdown == MHD_YES)
1400 return MHD_NO; 1411 return MHD_NO;
@@ -1408,23 +1419,91 @@ MHD_poll (struct MHD_Daemon *daemon,
1408 if (i >= num_connections) 1419 if (i >= num_connections)
1409 break; /* connection list changed somehow, retry later ... */ 1420 break; /* connection list changed somehow, retry later ... */
1410 MHD_connection_get_pollfd (pos, &mp); 1421 MHD_connection_get_pollfd (pos, &mp);
1411 if (p[1+i].fd != mp.fd) 1422 if (p[poll_server+i].fd != mp.fd)
1412 break; /* fd mismatch, something else happened, retry later ... */ 1423 break; /* fd mismatch, something else happened, retry later ... */
1413 1424
1414 /* normal handling */ 1425 /* normal handling */
1415 if (0 != (p[1+i].revents & POLLIN)) 1426 if (0 != (p[poll_server+i].revents & POLLIN))
1416 pos->read_handler (pos); 1427 pos->read_handler (pos);
1417 if (0 != (p[1+i].revents & POLLOUT)) 1428 if (0 != (p[poll_server+i].revents & POLLOUT))
1418 pos->write_handler (pos); 1429 pos->write_handler (pos);
1419 if (pos->socket_fd != -1) 1430 if (pos->socket_fd != -1)
1420 pos->idle_handler (pos); 1431 pos->idle_handler (pos);
1421 i++; 1432 i++;
1422 pos = pos->next; 1433 pos = pos->next;
1423 } 1434 }
1424 if (0 != (p[0].revents & POLLIN)) 1435 if ( (1 == poll_server) &&
1436 (0 != (p[0].revents & POLLIN)) )
1425 MHD_accept_connection (daemon); 1437 MHD_accept_connection (daemon);
1426 } 1438 }
1427 return MHD_YES; 1439 return MHD_YES;
1440}
1441
1442
1443/**
1444 * Process only the listen socket using 'poll'.
1445 *
1446 * @param daemon daemon to run poll loop for
1447 * @param may_block YES if blocking, NO if non-blocking
1448 * @return MHD_NO on serious errors, MHD_YES on success
1449 */
1450static int
1451MHD_poll_listen_socket (struct MHD_Daemon *daemon,
1452 int may_block)
1453{
1454 struct pollfd p;
1455 unsigned MHD_LONG_LONG ltimeout;
1456 int timeout;
1457
1458 memset (&p, 0, sizeof (p));
1459 p.fd = daemon->socket_fd;
1460 p.events = POLLIN;
1461 p.revents = 0;
1462 if (may_block == MHD_NO)
1463 timeout = 0;
1464 else if (MHD_YES != MHD_get_timeout (daemon, &ltimeout))
1465 timeout = -1;
1466 else
1467 timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout;
1468 if (poll (&p, 1, timeout) < 0)
1469 {
1470 if (errno == EINTR)
1471 return MHD_YES;
1472#if HAVE_MESSAGES
1473 MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno));
1474#endif
1475 return MHD_NO;
1476 }
1477 /* handle shutdown cases */
1478 if (daemon->shutdown == MHD_YES)
1479 return MHD_NO;
1480 if (daemon->socket_fd < 0)
1481 return MHD_YES;
1482 if (0 != (p.revents & POLLIN))
1483 MHD_accept_connection (daemon);
1484 return MHD_YES;
1485}
1486#endif
1487
1488
1489/**
1490 * Do 'poll'-based processing.
1491 *
1492 * @param daemon daemon to run poll loop for
1493 * @param may_block YES if blocking, NO if non-blocking
1494 * @return MHD_NO on serious errors, MHD_YES on success
1495 */
1496static int
1497MHD_poll (struct MHD_Daemon *daemon,
1498 int may_block)
1499{
1500#ifdef HAVE_POLL_H
1501 if (daemon->shutdown == MHD_YES)
1502 return MHD_NO;
1503 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1504 return MHD_poll_all (daemon, may_block);
1505 else
1506 return MHD_poll_listen_socket (daemon, may_block);
1428#else 1507#else
1429 return MHD_NO; 1508 return MHD_NO;
1430#endif 1509#endif