mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
fix game crashing when socket fd is >= 1024 on linux (Thanks Odd0002)
This commit is contained in:
parent
eb0251a7f9
commit
00d3afeb53
@ -1281,6 +1281,7 @@ CC_NOINLINE static void UpdatesScreen_FormatTime(String* str, char* type, int de
|
|||||||
static void UpdatesScreen_Format(struct LLabel* lbl, const char* prefix, TimeMS time) {
|
static void UpdatesScreen_Format(struct LLabel* lbl, const char* prefix, TimeMS time) {
|
||||||
String str; char buffer[STRING_SIZE];
|
String str; char buffer[STRING_SIZE];
|
||||||
TimeMS now;
|
TimeMS now;
|
||||||
|
int delta;
|
||||||
|
|
||||||
String_InitArray(str, buffer);
|
String_InitArray(str, buffer);
|
||||||
String_AppendConst(&str, prefix);
|
String_AppendConst(&str, prefix);
|
||||||
@ -1289,7 +1290,7 @@ static void UpdatesScreen_Format(struct LLabel* lbl, const char* prefix, TimeMS
|
|||||||
String_AppendConst(&str, "&cCheck failed");
|
String_AppendConst(&str, "&cCheck failed");
|
||||||
} else {
|
} else {
|
||||||
now = DateTime_CurrentUTC_MS();
|
now = DateTime_CurrentUTC_MS();
|
||||||
int delta = (int)(now - time) / 1000;
|
delta = (int)(now - time) / 1000;
|
||||||
|
|
||||||
if (delta < SECS_PER_MIN) {
|
if (delta < SECS_PER_MIN) {
|
||||||
UpdatesScreen_FormatTime(&str, "second", delta, 1);
|
UpdatesScreen_FormatTime(&str, "second", delta, 1);
|
||||||
|
@ -223,10 +223,6 @@ void LWebTask_Tick(struct LWebTask* task) {
|
|||||||
ASyncRequest_Free(&req);
|
ASyncRequest_Free(&req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LWebTask_DefaultBegin(struct LWebTask* task) {
|
|
||||||
AsyncDownloader_GetData(&task->URL, false, &task->Identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-------------------------------------------------------GetTokenTask------------------------------------------------------*
|
*-------------------------------------------------------GetTokenTask------------------------------------------------------*
|
||||||
|
@ -71,6 +71,7 @@ const ReturnCode ReturnCode_SocketWouldBlock = WSAEWOULDBLOCK;
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#define Socket__Error() errno
|
#define Socket__Error() errno
|
||||||
char* Platform_NewLine = "\n";
|
char* Platform_NewLine = "\n";
|
||||||
@ -875,17 +876,6 @@ static bool Font_MakeArgs(const String* path, FT_Stream stream, FT_Open_Args* ar
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Font_Find(const String* name, StringsBuffer* entries) {
|
|
||||||
String faceName;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 1; i < entries->Count; i += 2) {
|
|
||||||
faceName = StringsBuffer_UNSAFE_Get(entries, i);
|
|
||||||
if (String_CaselessEquals(&faceName, name)) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Font_GetNames(StringsBuffer* buffer) {
|
void Font_GetNames(StringsBuffer* buffer) {
|
||||||
String entry, name, path;
|
String entry, name, path;
|
||||||
int i;
|
int i;
|
||||||
@ -1273,33 +1263,62 @@ ReturnCode Socket_Close(SocketHandle socket) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success) {
|
/* Alas, a simple cross-platform select() is not good enough */
|
||||||
|
#ifdef CC_BUILD_WIN
|
||||||
|
ReturnCode Socket_Poll(SocketHandle socket, int mode, bool* success) {
|
||||||
fd_set set;
|
fd_set set;
|
||||||
struct timeval time = { 0 };
|
struct timeval time = { 0 };
|
||||||
int selectCount, nfds;
|
int selectCount;
|
||||||
|
|
||||||
|
set.fd_count = 1;
|
||||||
|
set.fd_array[0] = socket;
|
||||||
|
|
||||||
|
if (mode == SOCKET_POLL_READ) {
|
||||||
|
selectCount = select(1, &set, NULL, NULL, &time);
|
||||||
|
} else {
|
||||||
|
selectCount = select(1, NULL, &set, NULL, &time);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectCount == -1) { *success = false; return Socket__Error(); }
|
||||||
|
|
||||||
|
*success = set.fd_count != 0; return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef CC_BUILD_OSX
|
||||||
|
/* poll is broken on old OSX apparently https://daniel.haxx.se/docs/poll-vs-select.html */
|
||||||
|
ReturnCode Socket_Poll(SocketHandle socket, int mode, bool* success) {
|
||||||
|
fd_set set;
|
||||||
|
struct timeval time = { 0 };
|
||||||
|
int selectCount;
|
||||||
|
|
||||||
FD_ZERO(&set);
|
FD_ZERO(&set);
|
||||||
FD_SET(socket, &set);
|
FD_SET(socket, &set);
|
||||||
|
|
||||||
#ifdef CC_BUILD_WIN
|
if (selectMode == SOCKET_POLL_READ) {
|
||||||
nfds = 1;
|
selectCount = select(socket + 1, &set, NULL, NULL, &time);
|
||||||
#else
|
|
||||||
nfds = socket + 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (selectMode == SOCKET_SELECT_READ) {
|
|
||||||
selectCount = select(nfds, &set, NULL, NULL, &time);
|
|
||||||
} else {
|
} else {
|
||||||
selectCount = select(nfds, NULL, &set, NULL, &time);
|
selectCount = select(socket + 1, NULL, &set, NULL, &time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectCount == -1) { *success = false; return Socket__Error(); }
|
if (selectCount == -1) { *success = false; return Socket__Error(); }
|
||||||
#ifdef CC_BUILD_WIN
|
|
||||||
*success = set.fd_count != 0; return 0;
|
|
||||||
#else
|
|
||||||
*success = FD_ISSET(socket, &set); return 0;
|
*success = FD_ISSET(socket, &set); return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ReturnCode Socket_Poll(SocketHandle socket, int mode, bool* success) {
|
||||||
|
struct pollfd pfd;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
pfd.fd = socket;
|
||||||
|
pfd.events = mode == SOCKET_POLL_READ ? POLLIN : POLLOUT;
|
||||||
|
if (poll(&pfd, 1, 0) == -1) { *success = false; return Socket__Error(); }
|
||||||
|
|
||||||
|
/* to match select, closed socket still counts as readable */
|
||||||
|
flags = mode == SOCKET_POLL_READ ? (POLLIN | POLLHUP) : POLLOUT;
|
||||||
|
*success = (pfd.revents & flags) != 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
|
@ -9,7 +9,7 @@ struct DrawTextArgs;
|
|||||||
struct AsyncRequest;
|
struct AsyncRequest;
|
||||||
struct DateTime;
|
struct DateTime;
|
||||||
|
|
||||||
enum Socket_Select { SOCKET_SELECT_READ, SOCKET_SELECT_WRITE };
|
enum Socket_PollMode { SOCKET_POLL_READ, SOCKET_POLL_WRITE };
|
||||||
#ifdef CC_BUILD_WIN
|
#ifdef CC_BUILD_WIN
|
||||||
typedef uintptr_t SocketHandle;
|
typedef uintptr_t SocketHandle;
|
||||||
typedef void* FileHandle;
|
typedef void* FileHandle;
|
||||||
@ -201,13 +201,13 @@ int Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, Bitm
|
|||||||
void Socket_Create(SocketHandle* socket);
|
void Socket_Create(SocketHandle* socket);
|
||||||
/* Returns how much data is available to be read from the given socket. */
|
/* Returns how much data is available to be read from the given socket. */
|
||||||
ReturnCode Socket_Available(SocketHandle socket, uint32_t* available);
|
ReturnCode Socket_Available(SocketHandle socket, uint32_t* available);
|
||||||
/* Sets whether operations on this socket block the calling thread. */
|
/* Sets whether operations on the given socket block the calling thread. */
|
||||||
/* e.g. if blocking is on, calling Connect() blocks until a response is received. */
|
/* e.g. if blocking is on, calling Connect() blocks until a response is received. */
|
||||||
ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking);
|
ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking);
|
||||||
/* Returns (and resets) the last error generated by this socket. */
|
/* Returns (and resets) the last error generated by the given socket. */
|
||||||
ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result);
|
ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result);
|
||||||
|
|
||||||
/* Attempts to initalise a TCP connection to the given IP address:port. */
|
/* Attempts to initalise a connection to the given IP address:port. */
|
||||||
ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port);
|
ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port);
|
||||||
/* Attempts to read data from the given socket. */
|
/* Attempts to read data from the given socket. */
|
||||||
ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||||
@ -215,8 +215,10 @@ ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uin
|
|||||||
ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||||
/* Attempts to close the given socket. */
|
/* Attempts to close the given socket. */
|
||||||
ReturnCode Socket_Close(SocketHandle socket);
|
ReturnCode Socket_Close(SocketHandle socket);
|
||||||
/* Attempts to poll the socket for reading or writing. */
|
/* Attempts to poll the given socket for readability or writability. */
|
||||||
ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success);
|
/* NOTE: A closed socket is still considered readable. */
|
||||||
|
/* NOTE: A socket is considered writable once it has finished connecting. */
|
||||||
|
ReturnCode Socket_Poll(SocketHandle socket, int mode, bool* success);
|
||||||
|
|
||||||
/* Initalises the platform specific http library state. */
|
/* Initalises the platform specific http library state. */
|
||||||
void Http_Init(void);
|
void Http_Init(void);
|
||||||
|
@ -311,7 +311,7 @@ static void MPConnection_TickConnect(void) {
|
|||||||
if (res) { MPConnection_FailConnect(res); return; }
|
if (res) { MPConnection_FailConnect(res); return; }
|
||||||
|
|
||||||
now = DateTime_CurrentUTC_MS();
|
now = DateTime_CurrentUTC_MS();
|
||||||
Socket_Select(net_socket, SOCKET_SELECT_WRITE, &poll_write);
|
Socket_Poll(net_socket, SOCKET_POLL_WRITE, &poll_write);
|
||||||
|
|
||||||
if (poll_write) {
|
if (poll_write) {
|
||||||
Socket_SetBlocking(net_socket, true);
|
Socket_SetBlocking(net_socket, true);
|
||||||
@ -381,16 +381,17 @@ static void MPConnection_CheckDisconnection(double delta) {
|
|||||||
|
|
||||||
ReturnCode availRes, selectRes;
|
ReturnCode availRes, selectRes;
|
||||||
uint32_t pending = 0;
|
uint32_t pending = 0;
|
||||||
bool poll_success;
|
bool poll_read;
|
||||||
|
|
||||||
net_discAccumulator += delta;
|
net_discAccumulator += delta;
|
||||||
if (net_discAccumulator < 1.0) return;
|
if (net_discAccumulator < 1.0) return;
|
||||||
net_discAccumulator = 0.0;
|
net_discAccumulator = 0.0;
|
||||||
|
|
||||||
availRes = Socket_Available(net_socket, &pending);
|
availRes = Socket_Available(net_socket, &pending);
|
||||||
selectRes = Socket_Select(net_socket, SOCKET_SELECT_READ, &poll_success);
|
/* poll read returns true when socket is closed */
|
||||||
|
selectRes = Socket_Poll(net_socket, SOCKET_POLL_READ, &poll_read);
|
||||||
|
|
||||||
if (net_writeFailed || availRes || selectRes || (pending == 0 && poll_success)) {
|
if (net_writeFailed || availRes || selectRes || (pending == 0 && poll_read)) {
|
||||||
Game_Disconnect(&title, &reason);
|
Game_Disconnect(&title, &reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user