Skip to content

Commit 4125a55

Browse files
committed
Merge branch 'master' into for-0.56.0/sync
2 parents 5968902 + b508727 commit 4125a55

File tree

3 files changed

+101
-16
lines changed

3 files changed

+101
-16
lines changed

external_deps/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ setup_windows-amd64-mingw() {
11241124
# Set up environment for 64-bit amd64 macOS
11251125
setup_macos-amd64-default() {
11261126
MACOS_ARCH=x86_64
1127-
export MACOSX_DEPLOYMENT_TARGET=10.9 # works with CMake
1127+
export MACOSX_DEPLOYMENT_TARGET=10.12 # works with CMake
11281128
common_setup macos x86_64-apple-darwin11
11291129
}
11301130

src/engine/framework/System.cpp

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,96 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5454
namespace Sys {
5555
static Cvar::Cvar<bool> cvar_common_shutdownOnDrop("common.shutdownOnDrop", "shut down engine on game drop", Cvar::TEMPORARY, false);
5656

57+
static std::string singletonSocketPath;
5758
#ifdef _WIN32
5859
static HANDLE singletonSocket;
5960
#else
61+
#define SINGLETON_SOCKET_BASENAME "socket"
6062
static int singletonSocket;
6163
static FS::File lockFile;
6264
static bool haveSingletonLock = false;
65+
66+
static void FillSocketStruct(struct sockaddr_un &addr)
67+
{
68+
addr.sun_family = AF_UNIX;
69+
#ifdef __APPLE__
70+
Q_strncpyz(addr.sun_path, SINGLETON_SOCKET_BASENAME, sizeof(addr.sun_path));
71+
#else
72+
if (singletonSocketPath.size() > sizeof(addr.sun_path)) {
73+
Sys::Error("Singleton socket name '%s' is too long. Try configuring a shorter $TMPDIR",
74+
singletonSocketPath);
75+
}
76+
Q_strncpyz(addr.sun_path, singletonSocketPath.c_str(), sizeof(addr.sun_path));
6377
#endif
64-
static std::string singletonSocketPath;
78+
}
79+
80+
#ifdef __APPLE__
81+
// Secret Apple APIs. Chrome just declares them like this
82+
extern "C" {
83+
int pthread_chdir_np(const char* path);
84+
int pthread_fchdir_np(int fd);
85+
}
86+
87+
// These ChdirWrapper* functions return 0 on success or an errno on failure
88+
static int ChdirWrapperSingletonSocketConnect()
89+
{
90+
std::string dirName = FS::Path::DirName(singletonSocketPath);
91+
int error = 0;
92+
if (0 == pthread_chdir_np(dirName.c_str())) {
93+
struct sockaddr_un addr;
94+
FillSocketStruct(addr);
95+
if (0 != connect(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) {
96+
error = errno;
97+
}
98+
} else {
99+
// Assume the directory didn't exist. If it does but it is not accessible, we should
100+
// hit another error soon when trying to create the singleton socket
101+
error = ENOENT;
102+
}
103+
pthread_fchdir_np(-1); // reset CWD
104+
return error;
105+
}
106+
107+
static int ChdirWrapperSingletonSocketBind()
108+
{
109+
std::string dirName = FS::Path::DirName(singletonSocketPath);
110+
bool chdirSuccess = 0 == pthread_chdir_np(dirName.c_str());
111+
int error = 0;
112+
if (chdirSuccess) {
113+
struct sockaddr_un addr;
114+
FillSocketStruct(addr);
115+
if (0 != bind(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) {
116+
error = errno;
117+
}
118+
}
119+
pthread_fchdir_np(-1); // reset CWD
120+
if (!chdirSuccess) {
121+
Sys::Error("Failed to create or failed to access singleton socket directory '%s'", dirName);
122+
}
123+
return error;
124+
}
125+
#else // ! ifdef __APPLE__
126+
// TODO: supposedly there is an API that can be used to make chdir thread safe
127+
// on Linux too called "unshare"?
128+
static int ChdirWrapperSingletonSocketConnect()
129+
{
130+
struct sockaddr_un addr;
131+
FillSocketStruct(addr);
132+
return 0 == connect(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))
133+
? 0
134+
: errno;
135+
}
136+
137+
static int ChdirWrapperSingletonSocketBind()
138+
{
139+
struct sockaddr_un addr;
140+
FillSocketStruct(addr);
141+
return 0 == bind(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))
142+
? 0
143+
: errno;
144+
}
145+
#endif // ! ifdef __APPLE__
146+
#endif // ! ifdef _WIN32
65147

66148
// Get the path of a singleton socket
67149
std::string GetSingletonSocketPath()
@@ -78,7 +160,8 @@ std::string GetSingletonSocketPath()
78160
// We use a temporary directory rather that using the homepath because
79161
// socket paths are limited to about 100 characters. This also avoids issues
80162
// when the homepath is on a network filesystem.
81-
return FS::Path::Build(FS::Path::Build(FS::DefaultTempPath(), "." PRODUCT_NAME_LOWER + suffix), "socket");
163+
return FS::Path::Build(FS::Path::Build(
164+
FS::DefaultTempPath(), "." PRODUCT_NAME_LOWER + suffix), SINGLETON_SOCKET_BASENAME);
82165
#endif
83166
}
84167

@@ -120,11 +203,9 @@ static void CreateSingletonSocket()
120203
fchmod(singletonSocket, 0600);
121204
mkdir(dirName.c_str(), 0700);
122205

123-
struct sockaddr_un addr;
124-
addr.sun_family = AF_UNIX;
125-
Q_strncpyz(addr.sun_path, singletonSocketPath.c_str(), sizeof(addr.sun_path));
126-
if (bind(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1)
127-
Sys::Error("Could not bind singleton socket at file: \"%s\", error: \"%s\"", singletonSocketPath, strerror(errno) );
206+
int bindErr = ChdirWrapperSingletonSocketBind();
207+
if (bindErr != 0)
208+
Sys::Error("Could not bind singleton socket at file: \"%s\", error: \"%s\"", singletonSocketPath, strerror(bindErr) );
128209

129210
if (listen(singletonSocket, SOMAXCONN) == -1)
130211
Sys::Error("Could not listen on singleton socket file \"%s\", error: \"%s\"", singletonSocketPath, strerror(errno) );
@@ -154,12 +235,10 @@ static bool ConnectSingletonSocket()
154235
if (singletonSocket == -1)
155236
Sys::Error("Could not create socket: %s", strerror(errno));
156237

157-
struct sockaddr_un addr;
158-
addr.sun_family = AF_UNIX;
159-
Q_strncpyz(addr.sun_path, singletonSocketPath.c_str(), sizeof(addr.sun_path));
160-
if (connect(singletonSocket, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) == -1) {
161-
if (errno != ENOENT)
162-
Log::Warn("Could not connect to existing instance: %s", strerror(errno));
238+
int connectErr = ChdirWrapperSingletonSocketConnect();
239+
if (connectErr != 0) {
240+
if (connectErr != ENOENT)
241+
Log::Warn("Could not connect to existing instance: %s", strerror(connectErr));
163242
close(singletonSocket);
164243
return false;
165244
}

src/engine/framework/VirtualMachine.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ static Cvar::Cvar<bool> vm_nacl_bootstrap(
8383
"Use NaCl bootstrap helper",
8484
Cvar::INIT, true);
8585

86+
static Cvar::Cvar<int> vm_timeout(
87+
"vm.timeout",
88+
"Receive timeout in seconds",
89+
Cvar::NONE, 2);
90+
8691
namespace VM {
8792

8893
// https://github.com/Unvanquished/Unvanquished/issues/944#issuecomment-744454772
@@ -502,8 +507,9 @@ void VMBase::Create()
502507

503508
// Only set a receive timeout for non-debug configurations, otherwise it
504509
// would get triggered by breakpoints.
505-
if (type != TYPE_NATIVE_DLL && !params.debug.Get())
506-
rootChannel.SetRecvTimeout(std::chrono::seconds(2));
510+
if (type != TYPE_NATIVE_DLL && !params.debug.Get()) {
511+
rootChannel.SetRecvTimeout(std::chrono::seconds(vm_timeout.Get()));
512+
}
507513

508514
// Read the ABI version detection ABI version from the root socket.
509515
// If this fails, we assume the remote process failed to start

0 commit comments

Comments
 (0)