summaryrefslogtreecommitdiffstats
path: root/third_party/wayland-proxy/wayland-proxy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/wayland-proxy/wayland-proxy.cpp')
-rw-r--r--third_party/wayland-proxy/wayland-proxy.cpp151
1 files changed, 101 insertions, 50 deletions
diff --git a/third_party/wayland-proxy/wayland-proxy.cpp b/third_party/wayland-proxy/wayland-proxy.cpp
index 900c1162d9..065035e5c9 100644
--- a/third_party/wayland-proxy/wayland-proxy.cpp
+++ b/third_party/wayland-proxy/wayland-proxy.cpp
@@ -46,33 +46,35 @@ void Print(const char* aFormat, ...) {
va_end(args);
}
-void Warning(const char* aOperation, bool aPrintErrno = true) {
- fprintf(stderr, "Warning: %s : %s\n",
- aOperation,
- aPrintErrno ? strerror(errno) : "");
+void Warning(const char* aOperation) {
+ fprintf(stderr, "Warning: %s : %s\n", aOperation, strerror(errno));
}
-void Error(const char* aOperation, bool aPrintErrno = true) {
- fprintf(stderr, "Error: %s : %s\n",
- aOperation,
- aPrintErrno ? strerror(errno) : "");
+void Error(const char* aOperation) {
+ fprintf(stderr, "Error: %s : %s\n", aOperation, strerror(errno));
+}
+
+void ErrorPlain(const char* aFormat, ...) {
+ va_list args;
+ va_start(args, aFormat);
+ vfprintf(stderr, aFormat, args);
+ va_end(args);
}
class WaylandMessage {
public:
bool Write(int aSocket);
- bool Loaded() const { return mLoaded && (mFds.size() || mData.size()); }
+ bool Loaded() const { return !mFailed && (mFds.size() || mData.size()); }
bool Failed() const { return mFailed; }
explicit WaylandMessage(int aSocket) { Read(aSocket); }
~WaylandMessage();
private:
- bool Read(int aSocket);
+ void Read(int aSocket);
private:
- bool mLoaded = false;
bool mFailed = false;
std::vector<int> mFds;
@@ -110,6 +112,10 @@ class ProxiedConnection {
// We don't have connected compositor yet. Try to connect
bool mCompositorConnected = false;
+ // Don't cycle endlessly over compositor connection
+ int mFailedCompositorConnections = 0;
+ static constexpr int sMaxFailedCompositorConnections = 100;
+
// We're disconnected from app or compositor. We will close this connection.
bool mFailed = false;
@@ -130,9 +136,9 @@ WaylandMessage::~WaylandMessage() {
}
}
-bool WaylandMessage::Read(int aSocket) {
+void WaylandMessage::Read(int aSocket) {
// We don't expect WaylandMessage re-read
- assert(!mLoaded && !mFailed);
+ assert(!Loaded() && !mFailed);
mData.resize(MAX_DATA_SIZE);
@@ -149,7 +155,7 @@ bool WaylandMessage::Read(int aSocket) {
if (msg.msg_flags & (MSG_CTRUNC | MSG_TRUNC)) {
Error("WaylandMessage::Read() data truncated, small buffer?");
mFailed = true;
- return false;
+ return;
}
if (ret < 1) {
@@ -157,12 +163,12 @@ bool WaylandMessage::Read(int aSocket) {
case EAGAIN:
case EINTR:
// Neither loaded nor failed, we'll try again later
- Print("WaylandMessage::Write() failed %s\n", strerror(errno));
- return false;
+ Print("WaylandMessage::Read() failed %s\n", strerror(errno));
+ return;
default:
- Error("WaylandMessage::Write() failed");
+ Error("WaylandMessage::Read() failed");
mFailed = true;
- return false;
+ return;
}
}
@@ -180,6 +186,11 @@ bool WaylandMessage::Read(int aSocket) {
int* data = (int*)CMSG_DATA(header);
int filenum = (int)((header->cmsg_len - CMSG_LEN(0)) / sizeof(int));
+ if (filenum > MAX_LIBWAY_FDS) {
+ ErrorPlain("WaylandMessage::Read(): too many files to read\n");
+ mFailed = true;
+ return;
+ }
for (int i = 0; i < filenum; i++) {
#ifdef DEBUG
int flags = fcntl(data[i], F_GETFL, 0);
@@ -191,13 +202,10 @@ bool WaylandMessage::Read(int aSocket) {
}
header = next;
}
-
- mLoaded = true;
- return true;
}
bool WaylandMessage::Write(int aSocket) {
- if (!mLoaded || mFailed) {
+ if (!Loaded()) {
return false;
}
@@ -214,8 +222,8 @@ bool WaylandMessage::Write(int aSocket) {
int filenum = mFds.size();
if (filenum) {
- if (filenum >= MAX_LIBWAY_FDS) {
- Error("WaylandMessage::Write() too many files to send\n", false);
+ if (filenum > MAX_LIBWAY_FDS) {
+ ErrorPlain("WaylandMessage::Write() too many files to send\n");
return false;
}
#ifdef DEBUG
@@ -318,11 +326,6 @@ struct pollfd* ProxiedConnection::LoadPollFd(struct pollfd* aPfds) {
}
bool ProxiedConnection::ConnectToCompositor() {
- if (!(mCompositorFlags & POLLOUT)) {
- // Try again later
- return true;
- }
-
struct sockaddr_un addr = {};
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, mWaylandDisplay);
@@ -339,6 +342,11 @@ bool ProxiedConnection::ConnectToCompositor() {
case EINTR:
case EISCONN:
case ETIMEDOUT:
+ mFailedCompositorConnections++;
+ if (mFailedCompositorConnections > sMaxFailedCompositorConnections) {
+ Error("ConnectToCompositor() connect() failed repeatedly");
+ return false;
+ }
// We can recover from these errors and try again
Warning("ConnectToCompositor() try again");
return true;
@@ -460,27 +468,65 @@ bool ProxiedConnection::Process() {
return !mFailed;
}
+bool WaylandProxy::CheckWaylandDisplay(const char* aWaylandDisplay) {
+ struct sockaddr_un addr = {};
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, aWaylandDisplay);
+
+ int sc = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+ if (sc == -1) {
+ Error("CheckWaylandDisplay(): failed to create socket");
+ return false;
+ }
+
+ bool ret =
+ connect(sc, (const struct sockaddr*)&addr,
+ sizeof(struct sockaddr_un)) != -1;
+ if (!ret) {
+ switch (errno) {
+ case EAGAIN:
+ case EALREADY:
+ case ECONNREFUSED:
+ case EINPROGRESS:
+ case EINTR:
+ case EISCONN:
+ case ETIMEDOUT:
+ // We can recover from these errors and try again
+ ret = true;
+ break;
+ default:
+ ErrorPlain(
+ "CheckWaylandDisplay(): Failed to connect to Wayland display '%s' error: %s\n",
+ mWaylandDisplay, strerror(errno));
+ break;
+ }
+ }
+
+ close(sc);
+ return ret;
+}
+
+
bool WaylandProxy::SetupWaylandDisplays() {
char* waylandDisplay = getenv("WAYLAND_DISPLAY_COMPOSITOR");
if (!waylandDisplay) {
waylandDisplay = getenv("WAYLAND_DISPLAY");
- if (!waylandDisplay) {
- Error("Init(), Missing Wayland display, WAYLAND_DISPLAY is empty.",
- false);
+ if (!waylandDisplay || waylandDisplay[0] == '\0') {
+ ErrorPlain("WaylandProxy::SetupWaylandDisplays(), Missing Wayland display, WAYLAND_DISPLAY is empty.\n");
return false;
}
}
char* XDGRuntimeDir = getenv("XDG_RUNTIME_DIR");
if (!XDGRuntimeDir) {
- Error("Init() Missing XDG_RUNTIME_DIR", false);
+ ErrorPlain("WaylandProxy::SetupWaylandDisplays() Missing XDG_RUNTIME_DIR\n");
return false;
}
// WAYLAND_DISPLAY can be absolute path
if (waylandDisplay[0] == '/') {
if (strlen(mWaylandDisplay) >= sMaxDisplayNameLen) {
- Error("Init() WAYLAND_DISPLAY is too large.", false);
+ ErrorPlain("WaylandProxy::SetupWaylandDisplays() WAYLAND_DISPLAY is too large.\n");
return false;
}
strcpy(mWaylandDisplay, waylandDisplay);
@@ -488,22 +534,27 @@ bool WaylandProxy::SetupWaylandDisplays() {
int ret = snprintf(mWaylandDisplay, sMaxDisplayNameLen, "%s/%s",
XDGRuntimeDir, waylandDisplay);
if (ret < 0 || ret >= sMaxDisplayNameLen) {
- Error("Init() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.", false);
+ ErrorPlain("WaylandProxy::SetupWaylandDisplays() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.\n");
return false;
}
}
- // Save original Wayland display variable for potential reuse
- setenv("WAYLAND_DISPLAY_COMPOSITOR", waylandDisplay, /* overwrite = */ true);
+ if (!CheckWaylandDisplay(mWaylandDisplay)) {
+ return false;
+ }
int ret = snprintf(mWaylandProxy, sMaxDisplayNameLen,
"%s/wayland-proxy-%d", XDGRuntimeDir, getpid());
if (ret < 0 || ret >= sMaxDisplayNameLen) {
- Error("Init() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.", false);
+ ErrorPlain("WaylandProxy::SetupWaylandDisplays() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.\n");
return false;
}
- Info("SetupWaylandDisplays() Wayland '%s' proxy '%s'\n", mWaylandDisplay, mWaylandProxy);
+ // Save original Wayland display variable for potential reuse
+ setenv("WAYLAND_DISPLAY_COMPOSITOR", waylandDisplay, /* overwrite = */ true);
+
+ Info("SetupWaylandDisplays() Wayland '%s' proxy '%s'\n",
+ mWaylandDisplay, mWaylandProxy);
return true;
}
@@ -698,7 +749,7 @@ WaylandProxy::~WaylandProxy() {
}
void* WaylandProxy::RunProxyThread(WaylandProxy* aProxy) {
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
pthread_setname_np(pthread_self(), "WaylandProxy");
#endif
aProxy->Run();
@@ -718,7 +769,7 @@ std::unique_ptr<WaylandProxy> WaylandProxy::Create() {
bool WaylandProxy::RunChildApplication(char* argv[]) {
if (!argv[0]) {
- Error("WaylandProxy::RunChildApplication: missing application to run", false);
+ ErrorPlain("WaylandProxy::RunChildApplication: missing application to run\n");
return false;
}
@@ -730,7 +781,9 @@ bool WaylandProxy::RunChildApplication(char* argv[]) {
if (mApplicationPID == 0) {
SetWaylandProxyDisplay();
if (execv(argv[0], argv) == -1) {
- ErrorPlain("WaylandProxy::RunChildApplication: failed to run %s error %s\n", argv[0], strerror(errno));
+ ErrorPlain(
+ "WaylandProxy::RunChildApplication: failed to run %s error %s\n",
+ argv[0], strerror(errno));
exit(1);
}
}
@@ -742,7 +795,7 @@ bool WaylandProxy::RunChildApplication(char* argv[]) {
bool WaylandProxy::RunThread() {
pthread_attr_t attr;
if (pthread_attr_init(&attr) != 0) {
- ErrorPlain("pthread_attr_init() failed\n");
+ ErrorPlain("WaylandProxy::RunThread(): pthread_attr_init() failed\n");
return false;
}
@@ -756,7 +809,7 @@ bool WaylandProxy::RunThread() {
mThreadRunning = pthread_create(&mThread, nullptr, (void* (*)(void*))RunProxyThread, this) == 0;
if (!mThreadRunning) {
- ErrorPlain("pthread_create() failed\n");
+ ErrorPlain("WaylandProxy::RunThread(): pthread_create() failed\n");
// If we failed to run proxy thread, set WAYLAND_DISPLAY back.
RestoreWaylandDisplay();
}
@@ -778,16 +831,14 @@ void WaylandProxy::Info(const char* aFormat, ...) {
va_end(args);
}
-void WaylandProxy::Warning(const char* aOperation, bool aPrintErrno) {
+void WaylandProxy::Warning(const char* aOperation) {
fprintf(stderr, "[%d] Wayland Proxy [%p] Warning: %s : %s\n",
- getpid(), this, aOperation,
- aPrintErrno ? strerror(errno) : "");
+ getpid(), this, aOperation, strerror(errno));
}
-void WaylandProxy::Error(const char* aOperation, bool aPrintErrno) {
+void WaylandProxy::Error(const char* aOperation) {
fprintf(stderr, "[%d] Wayland Proxy [%p] Error: %s : %s\n",
- getpid(), this, aOperation,
- aPrintErrno ? strerror(errno) : "");
+ getpid(), this, aOperation, strerror(errno));
}
void WaylandProxy::ErrorPlain(const char* aFormat, ...) {