diff options
| -rw-r--r-- | src/net.cpp | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/src/net.cpp b/src/net.cpp index 964097b..77f9acf 100644 --- a/src/net.cpp +++ b/src/net.cpp | |||
| @@ -1471,11 +1471,29 @@ void ThreadSocketHandler2(void* parg) | |||
| 1471 | #else | 1471 | #else |
| 1472 | socklen_t nTypeLen = sizeof(nType); | 1472 | socklen_t nTypeLen = sizeof(nType); |
| 1473 | #endif | 1473 | #endif |
| 1474 | if (getsockopt(pnode->hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nTypeLen) != 0) | 1474 | if (pnode->hSocket != INVALID_SOCKET && |
| 1475 | getsockopt(pnode->hSocket, SOL_SOCKET, SO_TYPE, (char*)&nType, &nTypeLen) != 0) | ||
| 1475 | { | 1476 | { |
| 1476 | printf("dropping node %s: its socket is no longer valid\n", | 1477 | printf("dropping node %s: its socket is no longer valid\n", |
| 1477 | pnode->addr.ToString().c_str()); | 1478 | pnode->addr.ToString().c_str()); |
| 1478 | pnode->fDisconnect = true; | 1479 | pnode->fDisconnect = true; |
| 1480 | |||
| 1481 | // Stop referring to it, or it goes back into the next | ||
| 1482 | // select() set and fails it again. | ||
| 1483 | // | ||
| 1484 | // Marking fDisconnect is not enough: a node is only | ||
| 1485 | // removed from vNodes once it has drained or once | ||
| 1486 | // DISCONNECT_DRAIN_SECS has passed, so one dead | ||
| 1487 | // descriptor kept failing select() for a full minute -- | ||
| 1488 | // and a failed select() zeroes both sets above, which | ||
| 1489 | // means NO peer is read on that pass. Measured on a | ||
| 1490 | // wedged pool: 1,027 consecutive passes over 61 | ||
| 1491 | // seconds, one bad socket, the entire node deaf. | ||
| 1492 | // | ||
| 1493 | // Not closed, only forgotten. getsockopt just told us | ||
| 1494 | // this descriptor is not ours any more; closing it now | ||
| 1495 | // is how an unrelated socket gets closed instead. | ||
| 1496 | pnode->hSocket = INVALID_SOCKET; | ||
| 1479 | } | 1497 | } |
| 1480 | } | 1498 | } |
| 1481 | } | 1499 | } |
| @@ -1548,6 +1566,10 @@ void ThreadSocketHandler2(void* parg) | |||
| 1548 | { | 1566 | { |
| 1549 | CheckForShutdown(0); | 1567 | CheckForShutdown(0); |
| 1550 | SOCKET hSocket = pnode->hSocket; | 1568 | SOCKET hSocket = pnode->hSocket; |
| 1569 | // Forgotten above because it was already invalid. FD_ISSET on it | ||
| 1570 | // is meaningless and recv()/send() would be operating on -1. | ||
| 1571 | if (hSocket == INVALID_SOCKET) | ||
| 1572 | continue; | ||
| 1551 | 1573 | ||
| 1552 | // | 1574 | // |
| 1553 | // Receive | 1575 | // Receive |