diff options
Diffstat (limited to 'src/sockcount.h')
| -rw-r--r-- | src/sockcount.h | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/sockcount.h b/src/sockcount.h index 19f0827..a42abb9 100644 --- a/src/sockcount.h +++ b/src/sockcount.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #ifndef BITFLASH_SOCKCOUNT_H | 23 | #ifndef BITFLASH_SOCKCOUNT_H |
| 24 | #define BITFLASH_SOCKCOUNT_H | 24 | #define BITFLASH_SOCKCOUNT_H |
| 25 | 25 | ||
| 26 | #include <cerrno> | ||
| 26 | #include <map> | 27 | #include <map> |
| 27 | #include <mutex> | 28 | #include <mutex> |
| 28 | 29 | ||
| @@ -52,6 +53,13 @@ struct BtfSockAccount | |||
| 52 | long long nOpened[SOCK_SITES]; | 53 | long long nOpened[SOCK_SITES]; |
| 53 | long long nClosed[SOCK_SITES]; | 54 | long long nClosed[SOCK_SITES]; |
| 54 | long long nCloseFailed[SOCK_SITES]; | 55 | long long nCloseFailed[SOCK_SITES]; |
| 56 | // Why the close failed, counted per code per site. Measured on a node with | ||
| 57 | // 3h51m of uptime: the program believed it held 58 sockets and Windows | ||
| 58 | // attributed 112 to the process, 47 of them bound to an ephemeral port and | ||
| 59 | // never connected -- against 55 closes that had returned an error. The | ||
| 60 | // shapes match, and the error code is the piece that says whether the | ||
| 61 | // descriptor is still there or was already gone. | ||
| 62 | std::map<int, long long> mapCloseErr[SOCK_SITES]; | ||
| 55 | long long nClosedUntagged; | 63 | long long nClosedUntagged; |
| 56 | BtfSockAccount() : nClosedUntagged(0) | 64 | BtfSockAccount() : nClosedUntagged(0) |
| 57 | { | 65 | { |
| @@ -102,8 +110,10 @@ inline int BtfCloseSocket(SOCKET hSocket) | |||
| 102 | } | 110 | } |
| 103 | #ifdef _WIN32 | 111 | #ifdef _WIN32 |
| 104 | int nRet = ::closesocket(hSocket); | 112 | int nRet = ::closesocket(hSocket); |
| 113 | int nErr = (nRet != 0) ? WSAGetLastError() : 0; | ||
| 105 | #else | 114 | #else |
| 106 | int nRet = ::close(hSocket); | 115 | int nRet = ::close(hSocket); |
| 116 | int nErr = (nRet != 0) ? errno : 0; | ||
| 107 | #endif | 117 | #endif |
| 108 | // A close that fails leaves the descriptor -- and on Windows the ephemeral | 118 | // A close that fails leaves the descriptor -- and on Windows the ephemeral |
| 109 | // port it holds -- in place. Counted because a socket the program believes | 119 | // port it holds -- in place. Counted because a socket the program believes |
| @@ -115,6 +125,7 @@ inline int BtfCloseSocket(SOCKET hSocket) | |||
| 115 | BtfSockAccount& a = BtfSockAccounting(); | 125 | BtfSockAccount& a = BtfSockAccounting(); |
| 116 | std::lock_guard<std::mutex> lock(a.mtx); | 126 | std::lock_guard<std::mutex> lock(a.mtx); |
| 117 | a.nCloseFailed[nSite]++; | 127 | a.nCloseFailed[nSite]++; |
| 128 | a.mapCloseErr[nSite][nErr]++; | ||
| 118 | } | 129 | } |
| 119 | return nRet; | 130 | return nRet; |
| 120 | } | 131 | } |
| @@ -134,4 +145,16 @@ inline void BtfSockSnapshot(long long* pOpened, long long* pClosed, long long* p | |||
| 134 | *pUntagged = a.nClosedUntagged; | 145 | *pUntagged = a.nClosedUntagged; |
| 135 | } | 146 | } |
| 136 | 147 | ||
| 148 | // The close-failure codes for one site, newest counts included. Separate call | ||
| 149 | // because the table above is fixed-width and this is a list of unknown length. | ||
| 150 | inline void BtfSockCloseErrors(int nSite, std::map<int, long long>& mapOut) | ||
| 151 | { | ||
| 152 | mapOut.clear(); | ||
| 153 | if (nSite < 0 || nSite >= SOCK_SITES) | ||
| 154 | return; | ||
| 155 | BtfSockAccount& a = BtfSockAccounting(); | ||
| 156 | std::lock_guard<std::mutex> lock(a.mtx); | ||
| 157 | mapOut = a.mapCloseErr[nSite]; | ||
| 158 | } | ||
| 159 | |||
| 137 | #endif | 160 | #endif |