SDL_net: windows: Patched to work on Windows.

From 95687a3e7d685e9ff74c80cfccd04bae2d405063 Mon Sep 17 00:00:00 2001
From: unknown <[EMAIL REDACTED]>
Date: Sun, 17 May 2026 21:33:32 -0400
Subject: [PATCH] windows: Patched to work on Windows.

SDL3's Windows implementation of SDL_RWLock is _way_ more picky than
Mac or Linux. Make sure we don't double-lock, unlock a lock that
isn't locked, or try to convert from read to write locking without
an unlock between them.

Fixes hangs when dealing with network interfaces, etc.
---
 src/SDL_net.c | 59 +++++++++++++++++++++++----------------------------
 1 file changed, 27 insertions(+), 32 deletions(-)

diff --git a/src/SDL_net.c b/src/SDL_net.c
index feb66d9..1966444 100644
--- a/src/SDL_net.c
+++ b/src/SDL_net.c
@@ -791,10 +791,7 @@ static void RefreshInterfaces(void)
 static bool InterfacesReady(void)
 {
     if (SDL_ShouldInit(&interface_init)) {
-        if (!interface_rwlock) {
-            interface_rwlock = SDL_CreateRWLock();
-        }
-        if (!interface_rwlock || !InitInterfaceChangeNotifications()) {
+        if (!InitInterfaceChangeNotifications()) {
             SDL_SetInitialized(&interface_init, false);
             return false;
         }
@@ -1037,6 +1034,11 @@ bool NET_Init(void)
         ipv6_broadcast_addr = CreateSDLNetAddrFromSockAddr((const struct sockaddr *) &sa_in6, sizeof (sa_in6));
     }
 
+    interface_rwlock = SDL_CreateRWLock();
+    if (!interface_rwlock) {
+        goto failed;
+    }
+
     return true;  // good to go.
 
 failed:
@@ -1100,20 +1102,20 @@ void NET_Quit(void)
         if (interfaces) {
             FreeNetworkInterfaces(interfaces, num_interfaces);
         }
-        if (interface_rwlock) {
-            SDL_DestroyRWLock(interface_rwlock);
-        }
         interfaces = NULL;
         num_interfaces = 0;
-        interface_rwlock = NULL;
         SDL_SetInitialized(&interface_init, false);
     }
 
     // asserts to catch that these shouldn't have ever been set if we never initialized interface_init...
     SDL_assert(!interfaces);
-    SDL_assert(!interface_rwlock);
     SDL_assert(num_interfaces == 0);
 
+    if (interface_rwlock) {
+        SDL_DestroyRWLock(interface_rwlock);
+        interface_rwlock = NULL;
+    }
+
     NET_UnrefAddress(ipv6_broadcast_addr);
     ipv6_broadcast_addr = NULL;
 
@@ -1887,38 +1889,30 @@ struct NET_DatagramSocket
     bool allow_broadcast;
 };
 
-
-// if `addr` isn't from NET_GetLocalAddresses(), lookup the actual NET_Address
-// that matches it. This is so people can get an interface address specified on
-// the command line by "resolving" the command line string into a NET_Address,
-// and we'll figure out if it matches here, if necessary.
-// Caller must hold SDL_LockRWLockForReading(interface_rwlock)!
-static NetworkInterface *GetInterfaceForAddress(NET_Address *addr)
+static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interface_index)
 {
-    if (!addr) {
-        SDL_InvalidParamError("interface");
+    NET_Address *retval = NULL;
+
+    NET_Address *iface = CreateSDLNetAddrFromSockAddr(ainfo->ai_addr, (SockLen) ainfo->ai_addrlen);
+    if (!iface) {
         return NULL;
-    } else if (!InterfacesReady()) {
+    }
+
+    NetworkInterface *ni = NULL;
+    if (!InterfacesReady()) {
+        NET_UnrefAddress(iface);
         return NULL;
     }
 
+    SDL_LockRWLockForReading(interface_rwlock);
+
     for (int i = 0; i < num_interfaces; i++) {
-        if (NET_CompareAddresses(addr, interfaces[i].address) == 0) {
-            return &interfaces[i];
+        if (NET_CompareAddresses(iface, interfaces[i].address) == 0) {
+            ni = &interfaces[i];
+            break;
         }
     }
 
-    return NULL;
-}
-
-static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interface_index)
-{
-    NET_Address *retval = NULL;
-
-    NET_Address *iface = CreateSDLNetAddrFromSockAddr(ainfo->ai_addr, (SockLen) ainfo->ai_addrlen);
-    SDL_LockRWLockForReading(interface_rwlock);
-    NetworkInterface *ni = GetInterfaceForAddress(iface);
-    NET_UnrefAddress(iface);
     if (!ni) {
         SDL_SetError("Not a network interface address");
     } else {
@@ -1932,6 +1926,7 @@ static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interfa
             SDL_SetError("Can't determine broadcast address for this interface");
         }
     }
+
     SDL_UnlockRWLock(interface_rwlock);
 
     if (!retval && (ainfo->ai_family == AF_INET6)) {   // we fake this for IPv6 on the all-nodes link-local multicast group.