upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/sockcount.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/sockcount.h')
-rw-r--r--src/sockcount.h23
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.
150inline 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