Skip to content

Commit 48be56d

Browse files
committed
-netthread fixes and implementation for linux
1 parent 01781ea commit 48be56d

3 files changed

Lines changed: 79 additions & 12 deletions

File tree

rehlds/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ void setupToolchain(NativeBinarySpec b) {
176176
cfg.linkerOptions.args '-Wl,--version-script=../version_script.lds', '-Wl,--gc-sections'
177177

178178
cfg.projectLibpath(project, '/lib/linux32')
179-
cfg.extraLibs 'rt', 'dl', 'm', 'steam_api', 'aelf32'
179+
cfg.extraLibs 'rt', 'dl', 'm', 'steam_api', 'aelf32', 'pthread'
180180
}
181181

182182
if (unitTestExecutable) {

rehlds/engine/net_ws.cpp

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ net_messages_t *normalqueue;
7171
HANDLE hNetThread;
7272
DWORD dwNetThreadId;
7373
CRITICAL_SECTION net_cs;
74+
#else
75+
pthread_mutex_t net_mutex;
76+
pthread_t hNetThread;
77+
#endif
78+
79+
#ifdef REHLDS_FIXES
80+
volatile bool net_thread_terminated;
7481
#endif
7582

7683
cvar_t net_address = { "net_address", "", 0, 0.0f, NULL };
@@ -100,22 +107,26 @@ cvar_t net_graphpos = { "net_graphpos", "1", FCVAR_ARCHIVE, 0.0f, NULL };
100107

101108
void NET_ThreadLock()
102109
{
103-
#ifdef _WIN32
104110
if (use_thread && net_thread_initialized)
105111
{
112+
#ifdef _WIN32
106113
EnterCriticalSection(&net_cs);
107-
}
114+
#else
115+
pthread_mutex_lock(&net_mutex);
108116
#endif // _WIN32
117+
}
109118
}
110119

111120
void NET_ThreadUnlock()
112121
{
113-
#ifdef _WIN32
114122
if (use_thread && net_thread_initialized)
115123
{
124+
#ifdef _WIN32
116125
LeaveCriticalSection(&net_cs);
117-
}
126+
#else
127+
pthread_mutex_unlock(&net_mutex);
118128
#endif // _WIN32
129+
}
119130
}
120131

121132
unsigned short Q_ntohs(unsigned short netshort)
@@ -1112,14 +1123,20 @@ int NET_Sleep()
11121123
}
11131124

11141125
tv.tv_sec = 0;
1126+
#ifdef REHLDS_FIXES
1127+
tv.tv_usec = 0.25 * 1000000;
1128+
#else
11151129
tv.tv_usec = 20 * 1000;
1130+
#endif
11161131

11171132
return select((int)(number + 1), &fdset, NULL, NULL, net_sleepforever == 0 ? &tv : NULL);
11181133
}
11191134

11201135
#ifdef _WIN32
1121-
11221136
DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
1137+
#else
1138+
void* NET_ThreadMain(void*)
1139+
#endif // _WIN32
11231140
{
11241141
while (true)
11251142
{
@@ -1130,6 +1147,14 @@ DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
11301147
{
11311148
NET_ThreadLock();
11321149

1150+
#ifdef REHLDS_FIXES
1151+
if(net_thread_terminated)
1152+
{
1153+
NET_ThreadUnlock();
1154+
return 0;
1155+
}
1156+
#endif
1157+
11331158
bret = NET_QueuePacket((netsrc_t)sock);
11341159
if (bret)
11351160
{
@@ -1163,31 +1188,40 @@ DWORD WINAPI NET_ThreadMain(LPVOID lpThreadParameter)
11631188

11641189
Sys_Sleep(1);
11651190
}
1166-
11671191
return 0;
11681192
}
11691193

1170-
#endif // _WIN32
1171-
11721194
void NET_StartThread()
11731195
{
11741196
if (use_thread)
11751197
{
11761198
if (!net_thread_initialized)
11771199
{
11781200
net_thread_initialized = TRUE;
1201+
#ifdef REHLDS_FIXES
1202+
net_thread_terminated = false;
1203+
#endif
11791204

11801205
#ifdef _WIN32
11811206
InitializeCriticalSection(&net_cs);
11821207
hNetThread = CreateThread(0, 0, NET_ThreadMain, 0, 0, &dwNetThreadId);
11831208
if (!hNetThread)
11841209
{
11851210
DeleteCriticalSection(&net_cs);
1211+
#else
1212+
// In-line: There are several cases where mutex can go recursive in one thread.
1213+
pthread_mutexattr_t net_mutex_attr;
1214+
pthread_mutexattr_init(&net_mutex_attr);
1215+
pthread_mutexattr_settype(&net_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
1216+
pthread_mutex_init(&net_mutex, &net_mutex_attr);
1217+
if(pthread_create(&hNetThread, nullptr, &NET_ThreadMain, nullptr) != 0)
1218+
{
1219+
pthread_mutex_destroy(&net_mutex);
1220+
#endif
11861221
net_thread_initialized = FALSE;
11871222
use_thread = FALSE;
11881223
Sys_Error("%s: Couldn't initialize network thread, run without -netthread\n", __func__);
11891224
}
1190-
#endif // _WIN32
11911225
}
11921226
}
11931227
}
@@ -1198,9 +1232,35 @@ void NET_StopThread()
11981232
{
11991233
if (net_thread_initialized)
12001234
{
1235+
#ifdef REHLDS_FIXES // Safe thread stopping.
1236+
NET_ThreadLock();
1237+
net_thread_terminated = true;
1238+
NET_ThreadUnlock();
1239+
#endif // REHLDS_FIXES
1240+
12011241
#ifdef _WIN32
1202-
TerminateThread(hNetThread, 0);
1242+
1243+
#ifdef REHLDS_FIXES
1244+
if(WaitForSingleObject(hNetThread, 0.5 * 1000) != WAIT_OBJECT_0) // Wait 0.5 second for thread to finish
1245+
#endif // REHLDS_FIXES
1246+
{
1247+
TerminateThread(hNetThread, 0); // Kill unresponsive thread.
1248+
}
12031249
DeleteCriticalSection(&net_cs);
1250+
1251+
#else // _WIN32
1252+
struct timespec ts;
1253+
if(clock_gettime(CLOCK_REALTIME, &ts) == -1) {
1254+
Sys_Error("%s: CLOCK_REALTIME ERROR: %s", __func__, NET_ErrorString(NET_GetLastError()));
1255+
}
1256+
ts.tv_nsec += 0.5 * 1000000000; // Wait 0.5 second for thread to finish
1257+
1258+
if(pthread_timedjoin_np(hNetThread, nullptr, &ts) != 0)
1259+
{
1260+
pthread_cancel(hNetThread); // Kill unresponsive thread.
1261+
pthread_join(hNetThread, nullptr);
1262+
}
1263+
pthread_mutex_destroy(&net_mutex);
12041264
#endif // _WIN32
12051265
net_thread_initialized = FALSE;
12061266
}
@@ -2013,9 +2073,15 @@ void NET_Init()
20132073
Cvar_RegisterVariable(&net_graphpos);
20142074

20152075
if (COM_CheckParm("-netthread"))
2076+
#if defined(REHLDS_FIXES) || defined(_WIN32) // -netthread will work either on windows or on fixed linux build.
20162077
use_thread = TRUE;
2078+
#else
2079+
use_thread = FALSE;
2080+
#endif
20172081

2018-
if (COM_CheckParm("-netsleep"))
2082+
#ifndef REHLDS_FIXES
2083+
if (COM_CheckParm("-netsleep")) // Sleeping forever is useless.
2084+
#endif
20192085
net_sleepforever = 0;
20202086

20212087
#ifdef _WIN32

rehlds/public/rehlds/osconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
#include <sys/types.h>
8181
#include <sys/sysinfo.h>
8282
#include <unistd.h>
83+
#include <pthread.h>
8384
#endif // _WIN32
8485

8586
#include <string>

0 commit comments

Comments
 (0)