Skip to content

Commit 95687a3

Browse files
committed
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.
1 parent e10b9ab commit 95687a3

1 file changed

Lines changed: 27 additions & 32 deletions

File tree

src/SDL_net.c

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -791,10 +791,7 @@ static void RefreshInterfaces(void)
791791
static bool InterfacesReady(void)
792792
{
793793
if (SDL_ShouldInit(&interface_init)) {
794-
if (!interface_rwlock) {
795-
interface_rwlock = SDL_CreateRWLock();
796-
}
797-
if (!interface_rwlock || !InitInterfaceChangeNotifications()) {
794+
if (!InitInterfaceChangeNotifications()) {
798795
SDL_SetInitialized(&interface_init, false);
799796
return false;
800797
}
@@ -1037,6 +1034,11 @@ bool NET_Init(void)
10371034
ipv6_broadcast_addr = CreateSDLNetAddrFromSockAddr((const struct sockaddr *) &sa_in6, sizeof (sa_in6));
10381035
}
10391036

1037+
interface_rwlock = SDL_CreateRWLock();
1038+
if (!interface_rwlock) {
1039+
goto failed;
1040+
}
1041+
10401042
return true; // good to go.
10411043

10421044
failed:
@@ -1100,20 +1102,20 @@ void NET_Quit(void)
11001102
if (interfaces) {
11011103
FreeNetworkInterfaces(interfaces, num_interfaces);
11021104
}
1103-
if (interface_rwlock) {
1104-
SDL_DestroyRWLock(interface_rwlock);
1105-
}
11061105
interfaces = NULL;
11071106
num_interfaces = 0;
1108-
interface_rwlock = NULL;
11091107
SDL_SetInitialized(&interface_init, false);
11101108
}
11111109

11121110
// asserts to catch that these shouldn't have ever been set if we never initialized interface_init...
11131111
SDL_assert(!interfaces);
1114-
SDL_assert(!interface_rwlock);
11151112
SDL_assert(num_interfaces == 0);
11161113

1114+
if (interface_rwlock) {
1115+
SDL_DestroyRWLock(interface_rwlock);
1116+
interface_rwlock = NULL;
1117+
}
1118+
11171119
NET_UnrefAddress(ipv6_broadcast_addr);
11181120
ipv6_broadcast_addr = NULL;
11191121

@@ -1887,38 +1889,30 @@ struct NET_DatagramSocket
18871889
bool allow_broadcast;
18881890
};
18891891

1890-
1891-
// if `addr` isn't from NET_GetLocalAddresses(), lookup the actual NET_Address
1892-
// that matches it. This is so people can get an interface address specified on
1893-
// the command line by "resolving" the command line string into a NET_Address,
1894-
// and we'll figure out if it matches here, if necessary.
1895-
// Caller must hold SDL_LockRWLockForReading(interface_rwlock)!
1896-
static NetworkInterface *GetInterfaceForAddress(NET_Address *addr)
1892+
static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interface_index)
18971893
{
1898-
if (!addr) {
1899-
SDL_InvalidParamError("interface");
1894+
NET_Address *retval = NULL;
1895+
1896+
NET_Address *iface = CreateSDLNetAddrFromSockAddr(ainfo->ai_addr, (SockLen) ainfo->ai_addrlen);
1897+
if (!iface) {
19001898
return NULL;
1901-
} else if (!InterfacesReady()) {
1899+
}
1900+
1901+
NetworkInterface *ni = NULL;
1902+
if (!InterfacesReady()) {
1903+
NET_UnrefAddress(iface);
19021904
return NULL;
19031905
}
19041906

1907+
SDL_LockRWLockForReading(interface_rwlock);
1908+
19051909
for (int i = 0; i < num_interfaces; i++) {
1906-
if (NET_CompareAddresses(addr, interfaces[i].address) == 0) {
1907-
return &interfaces[i];
1910+
if (NET_CompareAddresses(iface, interfaces[i].address) == 0) {
1911+
ni = &interfaces[i];
1912+
break;
19081913
}
19091914
}
19101915

1911-
return NULL;
1912-
}
1913-
1914-
static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interface_index)
1915-
{
1916-
NET_Address *retval = NULL;
1917-
1918-
NET_Address *iface = CreateSDLNetAddrFromSockAddr(ainfo->ai_addr, (SockLen) ainfo->ai_addrlen);
1919-
SDL_LockRWLockForReading(interface_rwlock);
1920-
NetworkInterface *ni = GetInterfaceForAddress(iface);
1921-
NET_UnrefAddress(iface);
19221916
if (!ni) {
19231917
SDL_SetError("Not a network interface address");
19241918
} else {
@@ -1932,6 +1926,7 @@ static NET_Address *FindBroadcastAddress(struct addrinfo *ainfo, Uint32 *interfa
19321926
SDL_SetError("Can't determine broadcast address for this interface");
19331927
}
19341928
}
1929+
19351930
SDL_UnlockRWLock(interface_rwlock);
19361931

19371932
if (!retval && (ainfo->ai_family == AF_INET6)) { // we fake this for IPv6 on the all-nodes link-local multicast group.

0 commit comments

Comments
 (0)