From e76b4c0b97c30c0c3b92bd4cccb30e53bfa3f563 Mon Sep 17 00:00:00 2001
From: Alam Ed Arias <alam@srb2.org>
Date: Sun, 30 Mar 2025 11:07:52 -0400
Subject: [PATCH] Threads: add codepaths to free memory on fails

---
 src/m_menu.c                    |  7 ++++--
 src/netcode/client_connection.c |  5 ++++-
 src/netcode/d_netfil.c          | 32 +++++++++++++++++++++++----
 src/netcode/i_tcp.c             |  6 ++++-
 src/netcode/mserv.c             | 39 +++++++++++++++++++++++----------
 src/sdl/i_threads.c             |  8 ++++++-
 6 files changed, 76 insertions(+), 21 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 57ebe15274..52e1197232 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -11519,8 +11519,11 @@ static void M_RoomMenu(INT32 choice)
 		}
 		I_unlock_mutex(ms_QueryId_mutex);
 
-		(void)I_spawn_thread("check-new-version",
-				(I_thread_fn)Check_new_version_thread, id);
+		if(!I_spawn_thread("check-new-version",
+				(I_thread_fn)Check_new_version_thread, id))
+		{
+			free(id);
+		}
 	}
 	else
 	{
diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c
index 2fe2c09689..c7749d0f0f 100644
--- a/src/netcode/client_connection.c
+++ b/src/netcode/client_connection.c
@@ -510,7 +510,10 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
 
 			ctx->room = room;
 
-			(void)I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx);
+			if (!I_spawn_thread("fetch-servers", (I_thread_fn)Fetch_servers_thread, ctx))
+			{
+				free(ctx);
+			}
 		}
 		else
 		{
diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c
index 1ed138f5f6..94e5449a8c 100644
--- a/src/netcode/d_netfil.c
+++ b/src/netcode/d_netfil.c
@@ -1604,6 +1604,7 @@ static int curlprogress_callback(void *clientp, curl_off_t dltotal, curl_off_t d
 boolean CURLPrepareFile(const char* url, int dfilenum)
 {
 	HTTP_login *login;
+	CURLcode cc;
 
 	if (!I_can_thread())
 		return false;
@@ -1615,13 +1616,28 @@ boolean CURLPrepareFile(const char* url, int dfilenum)
 
 	if (!multi_handle)
 	{
-		curl_global_init(CURL_GLOBAL_ALL);
-		multi_handle = curl_multi_init();
+		cc = curl_global_init(CURL_GLOBAL_ALL);
+		if (cc < 0)
+		{
+			I_OutputMsg("libcurl: curl_global_init() returned %d\n", cc);
+		}
+		else
+		{
+			multi_handle = curl_multi_init();
+		}
+		if (!multi_handle)
+		{
+			I_OutputMsg("libcurl: curl_multi_init() failed\n");
+			curl_global_cleanup();
+			return false;
+		}
 	}
 
 	http_handle = curl_easy_init();
-	if (http_handle && multi_handle)
+	if (http_handle)
 	{
+		CURLMcode mc;
+
 		I_mkdir(downloaddir, 0755);
 
 		curl_curfile = &fileneeded[dfilenum];
@@ -1678,7 +1694,15 @@ boolean CURLPrepareFile(const char* url, int dfilenum)
 		filedownload.current = dfilenum;
 		filedownload.http_running = true;
 
-		(void)I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL);
+		if (!I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL))
+		{
+			mc = curl_multi_cleanup(multi_handle);
+			if (mc != CURLM_OK) I_OutputMsg("libcurl: %s\n",  curl_multi_strerror(mc));
+			curl_global_cleanup();
+			multi_handle = NULL;
+			filedownload.http_running = false;
+			return false;
+		}
 
 		return true;
 	}
diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c
index 604f9fa2fa..bc89fb87e8 100644
--- a/src/netcode/i_tcp.c
+++ b/src/netcode/i_tcp.c
@@ -281,7 +281,11 @@ static void I_InitUPnP(void)
 	}
 	upnpuser = malloc(sizeof *upnpuser);
 	upnpuser->upnpc_started = 0;
-	(void)I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser);
+	if (!I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser))
+	{
+		UPNP_support = false;
+		free(upnpuser);
+	}
 }
 
 static void
diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c
index 966168c821..fdc0304c5b 100644
--- a/src/netcode/mserv.c
+++ b/src/netcode/mserv.c
@@ -392,11 +392,15 @@ void RegisterServer(void)
 #ifdef MASTERSERVER
 	if (I_can_thread())
 	{
-		(void)I_spawn_thread(
+		void *nsid = New_server_id();
+		if (!I_spawn_thread(
 				"register-server",
 				(I_thread_fn)Register_server_thread,
-				New_server_id()
-		);
+				nsid
+		))
+		{
+			free(nsid);
+		}
 	}
 	else
 	{
@@ -409,11 +413,15 @@ static void UpdateServer(void)
 {
 	if (I_can_thread())
 	{
-		(void)I_spawn_thread(
+		void *sid = Server_id();
+		if (!I_spawn_thread(
 				"update-server",
 				(I_thread_fn)Update_server_thread,
-				Server_id()
-		);
+				sid
+		))
+		{
+			free(sid);
+		}
 	}
 	else
 	{
@@ -426,11 +434,14 @@ void UnregisterServer(void)
 #ifdef MASTERSERVER
 	if (I_can_thread())
 	{
-		(void)I_spawn_thread(
+		if (!I_spawn_thread(
 				"unlist-server",
 				(I_thread_fn)Unlist_server_thread,
 				Server_id()
-		);
+		))
+		{
+			;
+		}
 	}
 	else
 	{
@@ -482,17 +493,21 @@ void MasterClient_Ticker(void)
 static void
 Set_api (const char *api)
 {
+	char *dapi = strdup(api);
 	if (I_can_thread())
 	{
-		(void)I_spawn_thread(
+		if (!I_spawn_thread(
 				"change-masterserver",
 				(I_thread_fn)Change_masterserver_thread,
-				strdup(api)
-		);
+				dapi
+		))
+		{
+			free(dapi);
+		}
 	}
 	else
 	{
-		HMS_set_api(strdup(api));
+		HMS_set_api(dapi);
 	}
 }
 
diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c
index 1ba21d5d14..64e9ae142c 100644
--- a/src/sdl/i_threads.c
+++ b/src/sdl/i_threads.c
@@ -171,6 +171,7 @@ I_spawn_thread (
 
 	if (! th)
 	{
+		I_OutputMsg("Failed to make memory for Thread: %s", name);
 		return false;
 	}
 
@@ -192,12 +193,17 @@ I_spawn_thread (
 			if (! th->thread)
 			{
 				I_OutputMsg("I_spawn_thread failed to make thread %s: %s\n", name, SDL_GetError());
-				abort();
 			}
 		}
 	}
 	I_unlock_mutex(i_thread_pool_mutex);
 
+	if (! th->thread)
+	{
+		free(th);
+		return false;
+	}
+
 	return true;
 }
 
-- 
GitLab