Temporary removed proxy cache (rhbz#2262959)
This commit is contained in:
parent
bdd9cac34e
commit
7658746ef7
849
D196554.diff
849
D196554.diff
@ -1,849 +0,0 @@
|
||||
diff --git a/third_party/wayland-proxy/moz.build b/third_party/wayland-proxy/moz.build
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/third_party/wayland-proxy/moz.build
|
||||
@@ -0,0 +1,16 @@
|
||||
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
+# vim: set filetype=python:
|
||||
+# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
+# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
+
|
||||
+with Files("**"):
|
||||
+ BUG_COMPONENT = ("Core", "Widget: Gtk")
|
||||
+
|
||||
+SOURCES += [
|
||||
+ "wayland-proxy.cpp",
|
||||
+]
|
||||
+EXPORTS += [
|
||||
+ "wayland-proxy.h",
|
||||
+]
|
||||
+FINAL_LIBRARY = "xul"
|
||||
diff --git a/third_party/wayland-proxy/wayland-proxy.h b/third_party/wayland-proxy/wayland-proxy.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/third_party/wayland-proxy/wayland-proxy.h
|
||||
@@ -0,0 +1,55 @@
|
||||
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
+ * This Source Code Form is subject to the terms of the Mozilla Public
|
||||
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
+
|
||||
+#ifndef _wayland_proxy_h_
|
||||
+#define _wayland_proxy_h_
|
||||
+
|
||||
+#include <poll.h>
|
||||
+#include <vector>
|
||||
+#include <fcntl.h>
|
||||
+#include <atomic>
|
||||
+#include <memory>
|
||||
+
|
||||
+typedef unsigned char byte;
|
||||
+
|
||||
+class ProxiedConnection;
|
||||
+
|
||||
+class WaylandProxy {
|
||||
+ public:
|
||||
+
|
||||
+ static std::unique_ptr<WaylandProxy> Create();
|
||||
+
|
||||
+ bool RunChildApplication(char* argv[]);
|
||||
+ bool RunThread();
|
||||
+
|
||||
+ void SetWaylandDisplay();
|
||||
+ static void SetVerbose(bool aVerbose);
|
||||
+
|
||||
+ ~WaylandProxy();
|
||||
+
|
||||
+ private:
|
||||
+ bool Init();
|
||||
+ void Run();
|
||||
+
|
||||
+ void SetWaylandProxyDisplay();
|
||||
+ static void* RunProxyThread(WaylandProxy* aProxy);
|
||||
+
|
||||
+ bool SetupWaylandDisplays();
|
||||
+ bool StartProxyServer();
|
||||
+ bool IsChildAppTerminated();
|
||||
+
|
||||
+ bool PollConnections();
|
||||
+ bool ProcessConnections();
|
||||
+
|
||||
+ private:
|
||||
+ // List of all Compositor <-> Application connections
|
||||
+ std::vector<std::unique_ptr<ProxiedConnection>> mConnections;
|
||||
+ int mProxyServerSocket = -1;
|
||||
+ pid_t mApplicationPID = 0;
|
||||
+ std::atomic<bool> mThreadRunning = false;
|
||||
+ pthread_t mThread;
|
||||
+};
|
||||
+
|
||||
+#endif // _wayland_proxy_h_
|
||||
diff --git a/third_party/wayland-proxy/wayland-proxy.cpp b/third_party/wayland-proxy/wayland-proxy.cpp
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/third_party/wayland-proxy/wayland-proxy.cpp
|
||||
@@ -0,0 +1,742 @@
|
||||
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
+ * This Source Code Form is subject to the terms of the Mozilla Public
|
||||
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
+
|
||||
+// This code is based on Rust implementation at
|
||||
+// https://github.com/the8472/weyland-p5000
|
||||
+
|
||||
+// Version 1.0
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <sys/un.h>
|
||||
+#include <spawn.h>
|
||||
+#include <poll.h>
|
||||
+#include <vector>
|
||||
+#include <cerrno>
|
||||
+#include <fcntl.h>
|
||||
+#include <unistd.h>
|
||||
+#include <memory>
|
||||
+#include <cassert>
|
||||
+#include <pthread.h>
|
||||
+#include <sched.h>
|
||||
+
|
||||
+#include "wayland-proxy.h"
|
||||
+
|
||||
+// The maximum number of fds libwayland can recvmsg at once
|
||||
+#define MAX_LIBWAY_FDS 28
|
||||
+#define MAX_DATA_SIZE 4096
|
||||
+#define POLL_TIMEOUT 30000
|
||||
+
|
||||
+// sockaddr_un has hardcoded max len of sun_path
|
||||
+#define MAX_WAYLAND_DISPLAY_NAME_LEN 108
|
||||
+
|
||||
+// Name of Wayland display provided by compositor
|
||||
+char sWaylandDisplay[MAX_WAYLAND_DISPLAY_NAME_LEN];
|
||||
+
|
||||
+// Name of Wayland display provided by us
|
||||
+char sWaylandProxy[MAX_WAYLAND_DISPLAY_NAME_LEN];
|
||||
+
|
||||
+bool sPrintInfo = false;
|
||||
+
|
||||
+void Info(const char* aFormat, ...) {
|
||||
+ if (!sPrintInfo) {
|
||||
+ return;
|
||||
+ }
|
||||
+ va_list args;
|
||||
+ va_start(args, aFormat);
|
||||
+ vfprintf(stderr, aFormat, args);
|
||||
+ va_end(args);
|
||||
+}
|
||||
+
|
||||
+void Warning(const char* aOperation, bool aPrintErrno = true) {
|
||||
+ fprintf(stderr, "Wayland Proxy warning: %s : %s\n", aOperation,
|
||||
+ aPrintErrno ? strerror(errno) : "");
|
||||
+}
|
||||
+
|
||||
+void Error(const char* aOperation, bool aPrintErrno = true) {
|
||||
+ fprintf(stderr, "Wayland Proxy error: %s : %s\n", aOperation,
|
||||
+ aPrintErrno ? 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() { return mLoaded && (mFds.size() || mData.size()); }
|
||||
+ bool Failed() { return mFailed; }
|
||||
+
|
||||
+ explicit WaylandMessage(int aSocket) { Read(aSocket); }
|
||||
+ ~WaylandMessage();
|
||||
+
|
||||
+ private:
|
||||
+ bool Read(int aSocket);
|
||||
+
|
||||
+ private:
|
||||
+ bool mLoaded = false;
|
||||
+ bool mFailed = false;
|
||||
+
|
||||
+ std::vector<int> mFds;
|
||||
+ std::vector<byte> mData;
|
||||
+};
|
||||
+
|
||||
+class ProxiedConnection {
|
||||
+ public:
|
||||
+ bool Init(int aChildSocket);
|
||||
+ bool IsConnected() { return mCompositorConnected; }
|
||||
+
|
||||
+ struct pollfd* AddToPollFd(struct pollfd* aPfds);
|
||||
+ struct pollfd* LoadPollFd(struct pollfd* aPfds);
|
||||
+
|
||||
+ // Process this connection (send/receive data).
|
||||
+ // Returns false if connection is broken and should be removed.
|
||||
+ bool Process();
|
||||
+
|
||||
+ ~ProxiedConnection();
|
||||
+
|
||||
+ private:
|
||||
+ // Try to connect to compositor. Returns false in case of fatal error.
|
||||
+ bool ConnectToCompositor();
|
||||
+
|
||||
+ bool TransferOrQueue(
|
||||
+ int aSourceSocket, int aSourcePollFlags, int aDestSocket,
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>>* aMessageQueue);
|
||||
+ bool FlushQueue(int aDestSocket, int aDestPollFlags,
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>>& aMessageQueue);
|
||||
+
|
||||
+ // We don't have connected compositor yet. Try to connect
|
||||
+ bool mCompositorConnected = false;
|
||||
+
|
||||
+ // We're disconnected from app or compositor. We will close this connection.
|
||||
+ bool mFailed = false;
|
||||
+
|
||||
+ int mCompositorSocket = -1;
|
||||
+ int mCompositorFlags = 0;
|
||||
+
|
||||
+ int mApplicationSocket = -1;
|
||||
+ int mApplicationFlags = 0;
|
||||
+
|
||||
+ // Stored proxied data
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>> mToCompositorQueue;
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>> mToApplicationQueue;
|
||||
+};
|
||||
+
|
||||
+WaylandMessage::~WaylandMessage() {
|
||||
+ for (auto const fd : mFds) {
|
||||
+ close(fd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool WaylandMessage::Read(int aSocket) {
|
||||
+ // We don't expect WaylandMessage re-read
|
||||
+ assert(!mLoaded && !mFailed);
|
||||
+
|
||||
+ mData.resize(MAX_DATA_SIZE);
|
||||
+
|
||||
+ struct msghdr msg = {0};
|
||||
+ struct iovec iov = {mData.data(), mData.size()};
|
||||
+ msg.msg_iov = &iov;
|
||||
+ msg.msg_iovlen = 1;
|
||||
+
|
||||
+ char cmsgdata[(CMSG_LEN(MAX_LIBWAY_FDS * sizeof(int32_t)))] = {0};
|
||||
+ msg.msg_control = &cmsgdata;
|
||||
+ msg.msg_controllen = sizeof(cmsgdata);
|
||||
+
|
||||
+ ssize_t ret = recvmsg(aSocket, &msg, MSG_CMSG_CLOEXEC | MSG_DONTWAIT);
|
||||
+ if (msg.msg_flags & (MSG_CTRUNC | MSG_TRUNC)) {
|
||||
+ Error("WaylandMessage::Read() data truncated, small buffer?");
|
||||
+ mFailed = true;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (ret < 1) {
|
||||
+ switch (errno) {
|
||||
+ case EAGAIN:
|
||||
+ case EINTR:
|
||||
+ // Neither loaded nor failed, we'll try again later
|
||||
+ Info("WaylandMessage::Write() failed %s\n", strerror(errno));
|
||||
+ return false;
|
||||
+ default:
|
||||
+ Error("WaylandMessage::Write() failed");
|
||||
+ mFailed = true;
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Set correct data size
|
||||
+ mData.resize(ret);
|
||||
+
|
||||
+ // Read cmsg
|
||||
+ struct cmsghdr* header = CMSG_FIRSTHDR(&msg);
|
||||
+ while (header) {
|
||||
+ struct cmsghdr* next = CMSG_NXTHDR(&msg, header);
|
||||
+ if (header->cmsg_level != SOL_SOCKET || header->cmsg_type != SCM_RIGHTS) {
|
||||
+ header = next;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ int* data = (int*)CMSG_DATA(header);
|
||||
+ int filenum = (int)((header->cmsg_len - CMSG_LEN(0)) / sizeof(int));
|
||||
+ for (int i = 0; i < filenum; i++) {
|
||||
+#ifdef DEBUG
|
||||
+ int flags = fcntl(data[i], F_GETFL, 0);
|
||||
+ if (flags == -1 && errno == EBADF) {
|
||||
+ Error("WaylandMessage::Read() invalid fd");
|
||||
+ }
|
||||
+#endif
|
||||
+ mFds.push_back(data[i]);
|
||||
+ }
|
||||
+ header = next;
|
||||
+ }
|
||||
+
|
||||
+ mLoaded = true;
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool WaylandMessage::Write(int aSocket) {
|
||||
+ if (!mLoaded || mFailed) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ struct msghdr msg = {0};
|
||||
+ struct iovec iov = {mData.data(), mData.size()};
|
||||
+ msg.msg_iov = &iov;
|
||||
+ msg.msg_iovlen = 1;
|
||||
+
|
||||
+ int filenum = mFds.size();
|
||||
+ if (filenum) {
|
||||
+ if (filenum >= MAX_LIBWAY_FDS) {
|
||||
+ Error("WaylandMessage::Write() too many files to send\n", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+#ifdef DEBUG
|
||||
+ for (int i = 0; i < filenum; i++) {
|
||||
+ int flags = fcntl(mFds[i], F_GETFL, 0);
|
||||
+ if (flags == -1 && errno == EBADF) {
|
||||
+ Error("WaylandMessage::Write() invalid fd\n");
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+ union {
|
||||
+ char buf[CMSG_SPACE(sizeof(int) * MAX_LIBWAY_FDS)];
|
||||
+ struct cmsghdr align;
|
||||
+ } cmsgu;
|
||||
+ memset(cmsgu.buf, 0, sizeof(cmsgu.buf));
|
||||
+
|
||||
+ msg.msg_control = cmsgu.buf;
|
||||
+ msg.msg_controllen = sizeof(cmsgu.buf);
|
||||
+ msg.msg_controllen = CMSG_SPACE(filenum * sizeof(int));
|
||||
+
|
||||
+ struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
|
||||
+ cmsg->cmsg_level = SOL_SOCKET;
|
||||
+ cmsg->cmsg_type = SCM_RIGHTS;
|
||||
+ cmsg->cmsg_len = CMSG_LEN(filenum * sizeof(int));
|
||||
+ memcpy(CMSG_DATA(cmsg), mFds.data(), filenum * sizeof(int));
|
||||
+ }
|
||||
+
|
||||
+ ssize_t ret = sendmsg(aSocket, &msg, MSG_CMSG_CLOEXEC | MSG_DONTWAIT);
|
||||
+ if (ret < 1) {
|
||||
+ switch (errno) {
|
||||
+ case EAGAIN:
|
||||
+ case EINTR:
|
||||
+ // Neither loaded nor failed, we'll try again later
|
||||
+ Info("WaylandMessage::Write() failed %s\n", strerror(errno));
|
||||
+ return false;
|
||||
+ default:
|
||||
+ Warning("WaylandMessage::Write() failed");
|
||||
+ mFailed = true;
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (ret != (ssize_t)mData.size()) {
|
||||
+ Info("WaylandMessage::Write() failed to write all data! (%d vs. %d)\n", ret,
|
||||
+ mData.size());
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+ProxiedConnection::~ProxiedConnection() {
|
||||
+ if (mCompositorSocket != -1) {
|
||||
+ close(mCompositorSocket);
|
||||
+ }
|
||||
+ if (mApplicationSocket != -1) {
|
||||
+ close(mApplicationSocket);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+bool ProxiedConnection::Init(int aApplicationSocket) {
|
||||
+ mApplicationSocket = aApplicationSocket;
|
||||
+ mCompositorSocket =
|
||||
+ socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
+ if (mCompositorSocket == -1) {
|
||||
+ Error("ProxiedConnection::Init() socket()");
|
||||
+ }
|
||||
+ return mApplicationSocket > 0 && mCompositorSocket > 0;
|
||||
+}
|
||||
+
|
||||
+struct pollfd* ProxiedConnection::AddToPollFd(struct pollfd* aPfds) {
|
||||
+ // Listen application's requests
|
||||
+ aPfds->fd = mApplicationSocket;
|
||||
+ aPfds->events = POLLIN;
|
||||
+
|
||||
+ // We're connected and we have data for appplication from compositor.
|
||||
+ // Add POLLOUT to request write to app socket.
|
||||
+ if (mCompositorConnected && mToApplicationQueue.size()) {
|
||||
+ aPfds->events |= POLLOUT;
|
||||
+ }
|
||||
+ aPfds++;
|
||||
+
|
||||
+ aPfds->fd = mCompositorSocket;
|
||||
+ // We're waiting for connection or we have data for compositor
|
||||
+ if (!mCompositorConnected || mToCompositorQueue.size()) {
|
||||
+ aPfds->events |= POLLOUT;
|
||||
+ }
|
||||
+ if (mCompositorConnected) {
|
||||
+ aPfds->events = POLLIN;
|
||||
+ }
|
||||
+ aPfds++;
|
||||
+
|
||||
+ return aPfds;
|
||||
+}
|
||||
+
|
||||
+struct pollfd* ProxiedConnection::LoadPollFd(struct pollfd* aPfds) {
|
||||
+ if (aPfds->fd != mApplicationSocket) {
|
||||
+ return aPfds;
|
||||
+ }
|
||||
+ mApplicationFlags = aPfds->revents;
|
||||
+ aPfds++;
|
||||
+ mCompositorFlags = aPfds->revents;
|
||||
+ aPfds++;
|
||||
+ return 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, sWaylandDisplay);
|
||||
+
|
||||
+ mCompositorConnected =
|
||||
+ connect(mCompositorSocket, (const struct sockaddr*)&addr,
|
||||
+ sizeof(struct sockaddr_un)) != -1;
|
||||
+ if (!mCompositorConnected) {
|
||||
+ 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
|
||||
+ Warning("ConnectToCompositor() try again");
|
||||
+ return true;
|
||||
+ default:
|
||||
+ Error("ConnectToCompositor() connect()");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+// Read data from aSourceSocket and try to twite them to aDestSocket.
|
||||
+// If data write fails, append them to aMessageQueue.
|
||||
+// Return
|
||||
+bool ProxiedConnection::TransferOrQueue(
|
||||
+ int aSourceSocket, int aSourcePollFlags, int aDestSocket,
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>>* aMessageQueue) {
|
||||
+ // Don't read if we don't have any data ready
|
||||
+ if (!(aSourcePollFlags & POLLIN)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ while (1) {
|
||||
+ int availableData = 0;
|
||||
+ if (ioctl(aSourceSocket, FIONREAD, &availableData) < 0) {
|
||||
+ // Broken connection, we're finished here
|
||||
+ Warning("ProxiedConnection::TransferOrQueue() broken source socket %s\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (availableData == 0) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ auto message = std::make_unique<WaylandMessage>(aSourceSocket);
|
||||
+ if (message->Failed()) {
|
||||
+ // Failed to read message due to error
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (!message->Loaded()) {
|
||||
+ // Let's try again
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (!message->Write(aDestSocket)) {
|
||||
+ if (message->Failed()) {
|
||||
+ // Failed to write and we can't recover
|
||||
+ return false;
|
||||
+ }
|
||||
+ aMessageQueue->push_back(std::move(message));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// Try to flush all data to aMessageQueue.
|
||||
+bool ProxiedConnection::FlushQueue(
|
||||
+ int aDestSocket, int aDestPollFlags,
|
||||
+ std::vector<std::unique_ptr<WaylandMessage>>& aMessageQueue) {
|
||||
+ // Can't write to destination yet
|
||||
+ if (!(aDestPollFlags & POLLOUT)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ while (aMessageQueue.size()) {
|
||||
+ if (!aMessageQueue[0]->Write(aDestSocket)) {
|
||||
+ return !aMessageQueue[0]->Failed();
|
||||
+ }
|
||||
+ aMessageQueue.erase(aMessageQueue.begin());
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool ProxiedConnection::Process() {
|
||||
+ if (mFailed) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Check if appplication is still listening
|
||||
+ if (mApplicationFlags & (POLLHUP | POLLERR)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Check if compositor is still listening
|
||||
+ if (mCompositorConnected) {
|
||||
+ if (mCompositorFlags & (POLLHUP | POLLERR)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ // Try to reconnect to compositor.
|
||||
+ if (!ConnectToCompositor()) {
|
||||
+ Info("Failed to connect to compositor\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ // We're not connected yet but ConnectToCompositor() didn't return
|
||||
+ // fatal error. Try again later.
|
||||
+ if (!mCompositorConnected) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ mFailed =
|
||||
+ !TransferOrQueue(mCompositorSocket, mCompositorFlags, mApplicationSocket,
|
||||
+ &mToApplicationQueue) ||
|
||||
+ !TransferOrQueue(mApplicationSocket, mApplicationFlags, mCompositorSocket,
|
||||
+ &mToCompositorQueue) ||
|
||||
+ !FlushQueue(mCompositorSocket, mCompositorFlags, mToCompositorQueue) ||
|
||||
+ !FlushQueue(mApplicationSocket, mApplicationFlags, mToApplicationQueue);
|
||||
+
|
||||
+ return !mFailed;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::SetupWaylandDisplays() {
|
||||
+ char* waylandDisplay = getenv("WAYLAND_DISPLAY");
|
||||
+ if (!waylandDisplay) {
|
||||
+ Error("Init(), Missing Wayland display, WAYLAND_DISPLAY is empty.", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ char* XDGRuntimeDir = getenv("XDG_RUNTIME_DIR");
|
||||
+ if (!XDGRuntimeDir) {
|
||||
+ Error("Init() Missing XDG_RUNTIME_DIR", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // WAYLAND_DISPLAY can be absolute path
|
||||
+ if (waylandDisplay[0] == '/') {
|
||||
+ if (strlen(sWaylandDisplay) >= MAX_WAYLAND_DISPLAY_NAME_LEN) {
|
||||
+ Error("Init() WAYLAND_DISPLAY is too large.", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+ strcpy(sWaylandDisplay, waylandDisplay);
|
||||
+ } else {
|
||||
+ int ret = snprintf(sWaylandDisplay, MAX_WAYLAND_DISPLAY_NAME_LEN, "%s/%s",
|
||||
+ XDGRuntimeDir, waylandDisplay);
|
||||
+ if (ret < 0 || ret >= MAX_WAYLAND_DISPLAY_NAME_LEN) {
|
||||
+ Error("Init() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ int ret = snprintf(sWaylandProxy, MAX_WAYLAND_DISPLAY_NAME_LEN,
|
||||
+ "%s/wayland-proxy-%d", XDGRuntimeDir, getpid());
|
||||
+ if (ret < 0 || ret >= MAX_WAYLAND_DISPLAY_NAME_LEN) {
|
||||
+ Error("Init() WAYLAND_DISPLAY/XDG_RUNTIME_DIR is too large.", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ Info("WaylandProxy Wayland '%s' proxy '%s'\n", sWaylandDisplay, sWaylandProxy);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::StartProxyServer() {
|
||||
+ mProxyServerSocket =
|
||||
+ socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
+ if (mProxyServerSocket == -1) {
|
||||
+ Error("StartProxyServer(): failed to create socket");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ struct sockaddr_un serverName = {0};
|
||||
+ serverName.sun_family = AF_UNIX;
|
||||
+ strcpy(serverName.sun_path, sWaylandProxy);
|
||||
+
|
||||
+ if (bind(mProxyServerSocket, (struct sockaddr*)&serverName,
|
||||
+ sizeof(serverName)) == -1) {
|
||||
+ Error("StartProxyServer(): bind() error");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (listen(mProxyServerSocket, 128) == -1) {
|
||||
+ Error("StartProxyServer(): listen() error");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::Init() {
|
||||
+ if (!SetupWaylandDisplays()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!StartProxyServer()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void WaylandProxy::SetWaylandProxyDisplay() {
|
||||
+ setenv("WAYLAND_DISPLAY", sWaylandProxy, true);
|
||||
+}
|
||||
+
|
||||
+void WaylandProxy::SetWaylandDisplay() {
|
||||
+ setenv("WAYLAND_DISPLAY", sWaylandDisplay, true);
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::IsChildAppTerminated() {
|
||||
+ if (!mApplicationPID) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ int status = 0;
|
||||
+ int ret = waitpid(mApplicationPID, &status, WNOHANG | WUNTRACED | WCONTINUED);
|
||||
+ if (ret == 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (ret == mApplicationPID) {
|
||||
+ // Child application is terminated, so quit too.
|
||||
+ return true;
|
||||
+ }
|
||||
+ bool terminate = (errno == ECHILD);
|
||||
+ Error("IsChildAppTerminated: waitpid() error");
|
||||
+ return terminate;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::PollConnections() {
|
||||
+ int nfds_max = mConnections.size() * 2 + 1;
|
||||
+
|
||||
+ struct pollfd pollfds[nfds_max];
|
||||
+ struct pollfd* addedPollfd = pollfds;
|
||||
+
|
||||
+ for (auto const& connection : mConnections) {
|
||||
+ addedPollfd = connection->AddToPollFd(addedPollfd);
|
||||
+ }
|
||||
+ int nfds = (addedPollfd - pollfds);
|
||||
+
|
||||
+ // If all connections are attached to compositor, add another one
|
||||
+ // for new potential connection from application.
|
||||
+ bool addNewConnection = mConnections.empty() ||
|
||||
+ mConnections.back()->IsConnected();
|
||||
+ if (addNewConnection) {
|
||||
+ addedPollfd->fd = mProxyServerSocket;
|
||||
+ addedPollfd->events = POLLIN;
|
||||
+ nfds++;
|
||||
+ }
|
||||
+ assert(addedPollfd < pollfds + nfds_max);
|
||||
+
|
||||
+ while (1) {
|
||||
+ int ret = poll(pollfds, nfds, POLL_TIMEOUT);
|
||||
+ if (ret == 0) {
|
||||
+ // No change on fds
|
||||
+ continue;
|
||||
+ } else if (ret > 0) {
|
||||
+ // We have FD to read
|
||||
+ break;
|
||||
+ } else if (ret == -1) {
|
||||
+ switch (errno) {
|
||||
+ case EINTR:
|
||||
+ case EAGAIN:
|
||||
+ if (IsChildAppTerminated()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ continue;
|
||||
+ default:
|
||||
+ Error("Run: poll() error");
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ struct pollfd* loadedPollfd = pollfds;
|
||||
+ for (auto const& connection : mConnections) {
|
||||
+ loadedPollfd = connection->LoadPollFd(loadedPollfd);
|
||||
+ }
|
||||
+
|
||||
+ assert(loadedPollfd == addedPollfd);
|
||||
+ assert(loadedPollfd < pollfds + nfds_max);
|
||||
+
|
||||
+ // Create a new connection if there's a new client waiting
|
||||
+ if (addNewConnection && (loadedPollfd->revents & POLLIN)) {
|
||||
+ Info("WaylandProxy: new child connection\n");
|
||||
+ int applicationSocket = accept4(loadedPollfd->fd, nullptr, nullptr,
|
||||
+ SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||
+ if (applicationSocket == -1) {
|
||||
+ switch (errno) {
|
||||
+ case EAGAIN:
|
||||
+ case EINTR:
|
||||
+ // Try again later
|
||||
+ break;
|
||||
+ default:
|
||||
+ Error("Faild to accept connection from application");
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ auto connection = std::make_unique<ProxiedConnection>();
|
||||
+ if (connection->Init(applicationSocket)) {
|
||||
+ mConnections.push_back(std::move(connection));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::ProcessConnections() {
|
||||
+ std::vector<std::unique_ptr<ProxiedConnection>>::iterator connection;
|
||||
+ for (connection = mConnections.begin(); connection != mConnections.end();) {
|
||||
+ if (!(*connection)->Process()) {
|
||||
+ Info("WaylandProxy: remove connection\n");
|
||||
+ connection = mConnections.erase(connection);
|
||||
+ if (!mConnections.size()) {
|
||||
+ // We removed last connection - quit.
|
||||
+ Info("WaylandProxy: removed last connection, quit\n");
|
||||
+ return false;
|
||||
+ }
|
||||
+ } else {
|
||||
+ connection++;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void WaylandProxy::Run() {
|
||||
+ while (!IsChildAppTerminated() && PollConnections() && ProcessConnections())
|
||||
+ ;
|
||||
+}
|
||||
+
|
||||
+WaylandProxy::~WaylandProxy() {
|
||||
+ Info("WaylandProxy terminated\n");
|
||||
+ if (mThreadRunning) {
|
||||
+ Info("WaylandProxy thread is still running, terminating.\n");
|
||||
+ pthread_cancel(mThread);
|
||||
+ pthread_join(mThread, nullptr);
|
||||
+ }
|
||||
+ unlink(sWaylandProxy);
|
||||
+ if (mProxyServerSocket != -1) {
|
||||
+ close(mProxyServerSocket);
|
||||
+ }
|
||||
+ SetWaylandDisplay();
|
||||
+}
|
||||
+
|
||||
+void* WaylandProxy::RunProxyThread(WaylandProxy* aProxy) {
|
||||
+#ifdef __linux__
|
||||
+ pthread_setname_np(pthread_self(), "WaylandProxy");
|
||||
+#endif
|
||||
+ aProxy->Run();
|
||||
+ aProxy->mThreadRunning = false;
|
||||
+ Info("WaylandProxy thread exited\n");
|
||||
+ return nullptr;
|
||||
+}
|
||||
+
|
||||
+std::unique_ptr<WaylandProxy> WaylandProxy::Create() {
|
||||
+ auto proxy = std::make_unique<WaylandProxy>();
|
||||
+ if (!proxy->Init()) {
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ Info("WaylandProxyCreated, display %s\n", sWaylandProxy);
|
||||
+ return proxy;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::RunChildApplication(char* argv[]) {
|
||||
+ if (!argv[0]) {
|
||||
+ Error("WaylandProxy::RunChildApplication: missing application to run", false);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ mApplicationPID = fork();
|
||||
+ if (mApplicationPID == -1) {
|
||||
+ Error("WaylandProxy::RunChildApplication: fork() error");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (mApplicationPID == 0) {
|
||||
+ SetWaylandProxyDisplay();
|
||||
+ if (execv(argv[0], argv) == -1) {
|
||||
+ ErrorPlain("WaylandProxy::RunChildApplication: failed to run %s error %s\n", argv[0], strerror(errno));
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Run();
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+bool WaylandProxy::RunThread() {
|
||||
+ pthread_attr_t attr;
|
||||
+ if (pthread_attr_init(&attr) != 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ sched_param param;
|
||||
+ if (pthread_attr_getschedparam(&attr, ¶m) == 0) {
|
||||
+ param.sched_priority = sched_get_priority_min(SCHED_RR);
|
||||
+ pthread_attr_setschedparam(&attr, ¶m);
|
||||
+ }
|
||||
+
|
||||
+ SetWaylandProxyDisplay();
|
||||
+
|
||||
+ mThreadRunning = pthread_create(&mThread, nullptr, (void* (*)(void*))RunProxyThread, this) == 0;
|
||||
+ if (!mThreadRunning) {
|
||||
+ // If we failed to run proxy thread, set WAYLAND_DISPLAY back.
|
||||
+ SetWaylandDisplay();
|
||||
+ }
|
||||
+
|
||||
+ pthread_attr_destroy(&attr);
|
||||
+ return mThreadRunning;
|
||||
+}
|
||||
+
|
||||
+void WaylandProxy::SetVerbose(bool aVerbose) { sPrintInfo = aVerbose; }
|
||||
diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
|
||||
--- a/widget/gtk/moz.build
|
||||
+++ b/widget/gtk/moz.build
|
||||
@@ -21,11 +21,15 @@
|
||||
|
||||
if CONFIG["COMPILE_ENVIRONMENT"]:
|
||||
DIRS += ["mozgtk"]
|
||||
|
||||
if CONFIG["MOZ_WAYLAND"]:
|
||||
- DIRS += ["wayland", "mozwayland"]
|
||||
+ DIRS += [
|
||||
+ "wayland",
|
||||
+ "mozwayland",
|
||||
+ "../../third_party/wayland-proxy"
|
||||
+ ]
|
||||
|
||||
if CONFIG["MOZ_ENABLE_VAAPI"]:
|
||||
DIRS += ["vaapitest"]
|
||||
|
||||
if CONFIG["MOZ_ENABLE_V4L2"]:
|
||||
|
111
D196555.diff
111
D196555.diff
@ -1,111 +0,0 @@
|
||||
diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
|
||||
--- a/toolkit/xre/nsAppRunner.cpp
|
||||
+++ b/toolkit/xre/nsAppRunner.cpp
|
||||
@@ -342,17 +342,28 @@
|
||||
# include "mozilla/WidgetUtilsGtk.h"
|
||||
# include <gtk/gtk.h>
|
||||
# ifdef MOZ_WAYLAND
|
||||
# include <gdk/gdkwayland.h>
|
||||
# include "mozilla/widget/nsWaylandDisplay.h"
|
||||
+# include "wayland-proxy.h"
|
||||
# endif
|
||||
# ifdef MOZ_X11
|
||||
# include <gdk/gdkx.h>
|
||||
# endif /* MOZ_X11 */
|
||||
#endif
|
||||
+
|
||||
+#if defined(MOZ_WAYLAND)
|
||||
+std::unique_ptr<WaylandProxy> gWaylandProxy;
|
||||
+#endif
|
||||
+
|
||||
#include "BinaryPath.h"
|
||||
|
||||
+#ifdef MOZ_LOGGING
|
||||
+# include "mozilla/Logging.h"
|
||||
+extern mozilla::LazyLogModule gWidgetWaylandLog;
|
||||
+#endif /* MOZ_LOGGING */
|
||||
+
|
||||
#ifdef FUZZING
|
||||
# include "FuzzerRunner.h"
|
||||
|
||||
namespace mozilla {
|
||||
FuzzerRunner* fuzzerRunner = 0;
|
||||
@@ -2790,10 +2801,13 @@
|
||||
if (gRemoteService) {
|
||||
gRemoteService->UnlockStartup();
|
||||
gRemoteService = nullptr;
|
||||
}
|
||||
#endif
|
||||
+#if defined(MOZ_WAYLAND)
|
||||
+ gWaylandProxy = nullptr;
|
||||
+#endif
|
||||
return LaunchChild(false, true);
|
||||
}
|
||||
} else {
|
||||
rv = ps->Alert(nullptr, killTitle.get(), killMessage.get());
|
||||
NS_ENSURE_SUCCESS_LOG(rv, rv);
|
||||
@@ -2904,10 +2918,13 @@
|
||||
if (gRemoteService) {
|
||||
gRemoteService->UnlockStartup();
|
||||
gRemoteService = nullptr;
|
||||
}
|
||||
#endif
|
||||
+#if defined(MOZ_WAYLAND)
|
||||
+ gWaylandProxy = nullptr;
|
||||
+#endif
|
||||
return LaunchChild(false, true);
|
||||
}
|
||||
|
||||
static bool gDoMigration = false;
|
||||
static bool gDoProfileReset = false;
|
||||
@@ -4709,20 +4726,36 @@
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
if (!isBackgroundTaskMode && !gfxPlatform::IsHeadless()) {
|
||||
const char* display_name = nullptr;
|
||||
bool saveDisplayArg = false;
|
||||
|
||||
+ bool waylandEnabled = IsWaylandEnabled();
|
||||
+# ifdef MOZ_WAYLAND
|
||||
+ auto* proxyEnv = getenv("MOZ_DISABLE_WAYLAND_PROXY");
|
||||
+ bool disableWaylandProxy = proxyEnv && *proxyEnv;
|
||||
+ if (!disableWaylandProxy && XRE_IsParentProcess() && waylandEnabled) {
|
||||
+# ifdef MOZ_LOGGING
|
||||
+ if (MOZ_LOG_TEST(gWidgetWaylandLog, mozilla::LogLevel::Debug)) {
|
||||
+ WaylandProxy::SetVerbose(true);
|
||||
+ }
|
||||
+# endif
|
||||
+ gWaylandProxy = WaylandProxy::Create();
|
||||
+ if (gWaylandProxy) {
|
||||
+ gWaylandProxy->RunThread();
|
||||
+ }
|
||||
+ }
|
||||
+# endif
|
||||
+
|
||||
// display_name is owned by gdk.
|
||||
display_name = gdk_get_display_arg_name();
|
||||
// if --display argument is given make sure it's
|
||||
// also passed to ContentChild::Init() by MOZ_GDK_DISPLAY.
|
||||
if (display_name) {
|
||||
SaveWordToEnv("MOZ_GDK_DISPLAY", nsDependentCString(display_name));
|
||||
saveDisplayArg = true;
|
||||
}
|
||||
|
||||
- bool waylandEnabled = IsWaylandEnabled();
|
||||
// On Wayland disabled builds read X11 DISPLAY env exclusively
|
||||
// and don't care about different displays.
|
||||
if (!waylandEnabled && !display_name) {
|
||||
display_name = PR_GetEnv("DISPLAY");
|
||||
if (!display_name) {
|
||||
@@ -5952,10 +5985,11 @@
|
||||
// gdk_display_close also calls gdk_display_manager_set_default_display
|
||||
// appropriately when necessary.
|
||||
if (!gfxPlatform::IsHeadless()) {
|
||||
# ifdef MOZ_WAYLAND
|
||||
WaylandDisplayRelease();
|
||||
+ gWaylandProxy = nullptr;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
XRE_DeinitCommandLine();
|
||||
|
@ -179,7 +179,7 @@ ExcludeArch: i686
|
||||
Summary: Mozilla Firefox Web browser
|
||||
Name: firefox
|
||||
Version: 122.0
|
||||
Release: 5%{?pre_tag}%{?dist}
|
||||
Release: 6%{?pre_tag}%{?dist}
|
||||
URL: https://www.mozilla.org/firefox/
|
||||
License: MPLv1.1 or GPLv2+ or LGPLv2+
|
||||
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz
|
||||
@ -259,8 +259,6 @@ Patch242: 0026-Add-KDE-integration-to-Firefox.patch
|
||||
Patch402: mozilla-1196777.patch
|
||||
Patch407: mozilla-1667096.patch
|
||||
Patch408: D167159.diff
|
||||
Patch409: D196554.diff
|
||||
Patch410: D196555.diff
|
||||
|
||||
# PGO/LTO patches
|
||||
Patch600: pgo.patch
|
||||
@ -565,8 +563,6 @@ This package contains results of tests executed during build.
|
||||
%patch402 -p1 -b .1196777
|
||||
%patch407 -p1 -b .1667096
|
||||
%patch408 -p1 -b .D167159
|
||||
%patch409 -p1 -b .D196554
|
||||
%patch410 -p1 -b .D196555
|
||||
|
||||
# PGO patches
|
||||
%if %{build_with_pgo}
|
||||
@ -1190,6 +1186,9 @@ fi
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
%changelog
|
||||
* Mon Feb 12 2024 Martin Stransky <stransky@redhat.com>- 122.0-6
|
||||
- Temporary removed proxy cache (rhbz#2262959)
|
||||
|
||||
* Wed Jan 31 2024 Martin Stransky <stransky@redhat.com>- 122.0-5
|
||||
- Disabled system libvpx due to WebRTC/camera issues (mzbz#1875201)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user