diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c
index 810453f45a9bca49ba22bde81d5e0dd57ddb07c2..6d9a2725a3c65fb93e3f1f3b89e47dcf0464ad05 100644
--- a/src/netcode/i_tcp.c
+++ b/src/netcode/i_tcp.c
@@ -134,6 +134,7 @@ typedef union
 #include "d_netfil.h"
 #include "i_tcp.h"
 #include "../m_argv.h"
+#include "../i_threads.h"
 
 #include "../doomstat.h"
 
@@ -263,12 +264,33 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
 
 #ifdef HAVE_MINIUPNPC // based on old XChat patch
 static void I_ShutdownUPnP(void);
+static void I_InitUPnP(void);
+I_mutex upnp_mutex;
 static struct UPNPUrls urls;
 static struct IGDdatas data;
 static char lanaddr[64];
+struct upnpdata
+{
+	int upnpc_started;
+};
+static struct upnpdata *upnpuser;
+static void init_upnpc_once(struct upnpdata *upnpdata);
+
+static void I_InitUPnP(void)
+{
+	upnpuser = malloc(sizeof *upnpuser);
+	upnpuser->upnpc_started = 0;
+	I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser);
+}
 
-static inline void I_InitUPnP(void)
+static void
+init_upnpc_once(struct upnpdata *upnpuserdata)
 {
+
+	if (upnpuserdata->upnpc_started != 0)
+		return;
+
+	I_lock_mutex(&upnp_mutex);
 	const char * const deviceTypes[] = {
 		"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
 		"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
@@ -311,35 +333,43 @@ static inline void I_InitUPnP(void)
 			I_AddExitFunc(I_ShutdownUPnP);
 		}
 		freeUPNPDevlist(devlist);
+		I_unlock_mutex(upnp_mutex);
 	}
 	else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
 	{
 		CONS_Printf(M_GetText("No UPnP devices discovered\n"));
 	}
+	upnpuserdata->upnpc_started =1;
 }
 
 static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
 {
+	I_lock_mutex(&upnp_mutex);
 	if (addr == NULL)
 		addr = lanaddr;
 	if (!urls.controlURL || urls.controlURL[0] == '\0')
 		return;
 	UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
 	                    port, port, addr, "SRB2", servicetype, NULL, NULL);
+	I_unlock_mutex(upnp_mutex);
 }
 
 static inline void I_UPnP_rem(const char *port, const char * servicetype)
 {
+	I_lock_mutex(&upnp_mutex);
 	if (!urls.controlURL || urls.controlURL[0] == '\0')
 		return;
 	UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
 	                       port, servicetype, NULL);
+	I_unlock_mutex(upnp_mutex);
 }
 
 static void I_ShutdownUPnP(void)
 {
 	I_UPnP_rem(serverport_name, "UDP");
+	I_lock_mutex(&upnp_mutex);
 	FreeUPNPUrls(&urls);
+	I_unlock_mutex(upnp_mutex);
 }
 #endif