netcode-revival: fix SetRelay deadlock + grant multiplayer privileges
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
- Deadlock: SetRelay held the transport mutex while join()ing the receive thread, which needs the mutex to observe running_ and exit. With the 200ms recv timeout the thread woke and hit the lock -> a room/server change froze the game (every room keystroke reconnects the transport). StopThread now detaches the thread under the lock and joins WITHOUT it. - XamUserCheckPrivilege denied everything, which is the gate the game's 'create a party' flow checks (multiplayer sessions); grant requested privileges so the P2P session flow opens, and log the mask.
This commit is contained in:
parent
3229aa3632
commit
6fcc96de18
3 changed files with 37 additions and 15 deletions
|
|
@ -138,7 +138,10 @@ class XNetTransport {
|
|||
XNetTransport& operator=(const XNetTransport&) = delete;
|
||||
|
||||
void Reconnect();
|
||||
void StopLocked();
|
||||
// Stop the receive thread and join it WITHOUT holding mu_ (the Run thread
|
||||
// needs mu_ to observe running_ and exit; joining under the lock deadlocks
|
||||
// once recvfrom times out and the thread tries to lock mu_).
|
||||
void StopThread();
|
||||
void Run();
|
||||
void HandlePacket(const uint8_t* data, int size);
|
||||
|
||||
|
|
|
|||
|
|
@ -430,8 +430,13 @@ u32 XamUserCheckPrivilege_entry(u32 user_index, u32 mask, mapped_u32 out_value)
|
|||
}
|
||||
}
|
||||
|
||||
// If we deny everything, games should hopefully not try to do stuff.
|
||||
*out_value = 0;
|
||||
// netcode-revival: the game gates its party/session flow on
|
||||
// XamUserCheckPrivilege (e.g. MULTIPLAYER_SESSIONS); denying everything
|
||||
// (the old default) made "create a party" refuse. Grant requested online
|
||||
// privileges so the P2P session flow opens.
|
||||
*out_value = 1;
|
||||
REXLOG_INFO("xam: XamUserCheckPrivilege(user={}, mask=0x{:08X}) -> granted",
|
||||
user_index, mask);
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -118,8 +118,16 @@ XNetTransport& XNetTransport::Instance() {
|
|||
}
|
||||
|
||||
XNetTransport::~XNetTransport() {
|
||||
StopThread(); // join outside the lock (see StopThread)
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
StopLocked();
|
||||
if (sock_ != -1) {
|
||||
SocketClose(sock_);
|
||||
sock_ = -1;
|
||||
}
|
||||
active_ = false;
|
||||
joined_ = false;
|
||||
sessions_.clear();
|
||||
sockets_.clear();
|
||||
}
|
||||
|
||||
uint32_t XNetTransport::LocalVirtualIp() {
|
||||
|
|
@ -156,17 +164,29 @@ void XNetTransport::SetRelay(const char* host, uint16_t port, const char* room)
|
|||
host_ = h;
|
||||
port_ = port;
|
||||
room_ = r;
|
||||
StopLocked();
|
||||
}
|
||||
StopThread(); // join the old thread OUTSIDE the lock
|
||||
Reconnect();
|
||||
}
|
||||
|
||||
void XNetTransport::StopLocked() {
|
||||
if (thread_.joinable()) {
|
||||
void XNetTransport::StopThread() {
|
||||
std::thread old;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
running_ = false;
|
||||
thread_.join();
|
||||
old = std::move(thread_);
|
||||
thread_ = {};
|
||||
}
|
||||
if (old.joinable()) {
|
||||
old.join();
|
||||
}
|
||||
}
|
||||
|
||||
void XNetTransport::Reconnect() {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
if (host_.empty() || port_ == 0) {
|
||||
return;
|
||||
}
|
||||
if (sock_ != -1) {
|
||||
SocketClose(sock_);
|
||||
sock_ = -1;
|
||||
|
|
@ -174,13 +194,7 @@ void XNetTransport::StopLocked() {
|
|||
active_ = false;
|
||||
joined_ = false;
|
||||
sessions_.clear();
|
||||
}
|
||||
|
||||
void XNetTransport::Reconnect() {
|
||||
std::lock_guard<std::mutex> lock(mu_);
|
||||
if (host_.empty() || port_ == 0) {
|
||||
return;
|
||||
}
|
||||
relay_resolved_ = false;
|
||||
sockaddr_in relay_addr = {};
|
||||
if (!Resolve(host_, port_, &relay_addr)) {
|
||||
REXLOG_WARN("xnet transport: cannot resolve relay '{}:{}'", host_, port_);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue