fix game crashing when socket fd is >= 1024 on linux (Thanks Odd0002)

This commit is contained in:
UnknownShadow200 2018-12-20 09:33:26 +11:00
parent eb0251a7f9
commit 00d3afeb53
5 changed files with 61 additions and 42 deletions

View File

@ -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);

View File

@ -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------------------------------------------------------*

View File

@ -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
/*########################################################################################################################* /*########################################################################################################################*

View File

@ -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);

View File

@ -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);
} }
} }