netcode-revival: receive timeout on the relay transport socket
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
Some checks are pending
Lint & Format Check / Format Check (push) Waiting to run
The Run thread blocked in recvfrom with no SO_RCVTIMEO, so when there was no inbound game traffic the 4s heartbeat never fired (the relay swept the silent transport client after ~8s) AND StopLocked()'s join() deadlocked SetRelay on a room change (hanging the ghost network loop). A 200ms receive timeout wakes the loop regularly: the heartbeat keeps the transport alive and shutdown/room-change joins complete promptly.
This commit is contained in:
parent
01fe706c13
commit
3ec27d115b
1 changed files with 19 additions and 0 deletions
|
|
@ -60,6 +60,23 @@ void SocketClose(int64_t s) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// The receive loop must wake regularly so the heartbeat fires even with no
|
||||
// inbound traffic (otherwise the relay sweeps a silent transport client
|
||||
// after ~8s) and so StopLocked()'s join completes promptly instead of
|
||||
// deadlocking SetRelay on a room change.
|
||||
void SocketSetRecvTimeout(int64_t s, int timeout_ms) {
|
||||
#if REX_PLATFORM_WIN32
|
||||
DWORD tv = DWORD(timeout_ms);
|
||||
::setsockopt(SOCKET(s), SOL_SOCKET, SO_RCVTIMEO,
|
||||
reinterpret_cast<const char*>(&tv), sizeof(tv));
|
||||
#else
|
||||
timeval tv = {};
|
||||
tv.tv_sec = timeout_ms / 1000;
|
||||
tv.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
::setsockopt(int(s), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SocketSendTo(int64_t s, const sockaddr_in* to, const void* buf, int size) {
|
||||
#if REX_PLATFORM_WIN32
|
||||
const int n = ::sendto(SOCKET(s), reinterpret_cast<const char*>(buf), size, 0,
|
||||
|
|
@ -176,6 +193,8 @@ void XNetTransport::Reconnect() {
|
|||
REXLOG_WARN("xnet transport: cannot open relay socket");
|
||||
return;
|
||||
}
|
||||
// Wake the receive loop every 200ms (heartbeat + prompt shutdown).
|
||||
SocketSetRecvTimeout(sock_, 200);
|
||||
REXLOG_INFO("xnet transport: connecting to relay '{}:{}' room '{}' (vip {}.{}.{}.{})", host_,
|
||||
port_, room_.c_str(), (LocalVirtualIp() >> 24) & 0xFF, (LocalVirtualIp() >> 16) & 0xFF,
|
||||
(LocalVirtualIp() >> 8) & 0xFF, LocalVirtualIp() & 0xFF);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue