freescale-layer: wayland: port patches from scarthgap-6.6.23-2.0.0 meta-imx
All wayland-related recipes save for these patches are already available in meta-freescale https://onedigi.atlassian.net/browse/DEL-9011 https://onedigi.atlassian.net/browse/DEL-9081 Signed-off-by: Gabriel Valcazar <gabriel.valcazar@digi.com>
This commit is contained in:
parent
d7ee944abb
commit
2d6ab24a6a
|
|
@ -0,0 +1,134 @@
|
|||
From 7a890bbf1d6eef0f1b52a701640afe2e495aaa8c Mon Sep 17 00:00:00 2001
|
||||
From: Wujian Sun <wujian.sun_1@nxp.com>
|
||||
Date: Wed, 29 Nov 2023 17:04:51 +0800
|
||||
Subject: [PATCH 1/4] Revert "client: Do not warn about attached proxies on
|
||||
default queue destruction."
|
||||
|
||||
This reverts commit b01a85dfd5e8cda7170b7ba6fe66fc3800f93990.
|
||||
Upstream-Status: Inappropriate [i.MX specific]
|
||||
---
|
||||
src/wayland-client.c | 14 ++++------
|
||||
tests/queue-test.c | 63 +-------------------------------------------
|
||||
2 files changed, 6 insertions(+), 71 deletions(-)
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index 105f9be..baebfa9 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -304,18 +304,14 @@ wl_event_queue_release(struct wl_event_queue *queue)
|
||||
if (!wl_list_empty(&queue->proxy_list)) {
|
||||
struct wl_proxy *proxy, *tmp;
|
||||
|
||||
- if (queue != &queue->display->default_queue) {
|
||||
- wl_log("warning: queue %p destroyed while proxies "
|
||||
- "still attached:\n", queue);
|
||||
- }
|
||||
+ wl_log("warning: queue %p destroyed while proxies still "
|
||||
+ "attached:\n", queue);
|
||||
|
||||
wl_list_for_each_safe(proxy, tmp, &queue->proxy_list,
|
||||
queue_link) {
|
||||
- if (queue != &queue->display->default_queue) {
|
||||
- wl_log(" %s@%u still attached\n",
|
||||
- proxy->object.interface->name,
|
||||
- proxy->object.id);
|
||||
- }
|
||||
+ wl_log(" %s@%u still attached\n",
|
||||
+ proxy->object.interface->name,
|
||||
+ proxy->object.id);
|
||||
proxy->queue = NULL;
|
||||
wl_list_remove(&proxy->queue_link);
|
||||
wl_list_init(&proxy->queue_link);
|
||||
diff --git a/tests/queue-test.c b/tests/queue-test.c
|
||||
index 4129310..63abc19 100644
|
||||
--- a/tests/queue-test.c
|
||||
+++ b/tests/queue-test.c
|
||||
@@ -308,22 +308,12 @@ client_test_queue_set_queue_race(void)
|
||||
}
|
||||
|
||||
static char *
|
||||
-maybe_map_file(int fd, size_t *len)
|
||||
+map_file(int fd, size_t *len)
|
||||
{
|
||||
char *data;
|
||||
|
||||
*len = lseek(fd, 0, SEEK_END);
|
||||
data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
-
|
||||
- return data;
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-map_file(int fd, size_t *len)
|
||||
-{
|
||||
- char *data;
|
||||
-
|
||||
- data = maybe_map_file(fd, len);
|
||||
assert(data != MAP_FAILED && "Failed to mmap file");
|
||||
|
||||
return data;
|
||||
@@ -432,45 +422,6 @@ client_test_queue_proxy_event_to_destroyed_queue(void)
|
||||
wl_display_disconnect(display);
|
||||
}
|
||||
|
||||
-static void
|
||||
-client_test_queue_destroy_default_with_attached_proxies(void)
|
||||
-{
|
||||
- struct wl_display *display;
|
||||
- struct wl_callback *callback;
|
||||
- char *log;
|
||||
- size_t log_len;
|
||||
- char callback_name[24];
|
||||
- int ret;
|
||||
-
|
||||
- display = wl_display_connect(NULL);
|
||||
- assert(display);
|
||||
-
|
||||
- /* Create a sync dispatching events on the default queue. */
|
||||
- callback = wl_display_sync(display);
|
||||
- assert(callback != NULL);
|
||||
-
|
||||
- /* Destroy the default queue (by disconnecting) before the attached
|
||||
- * object. */
|
||||
- wl_display_disconnect(display);
|
||||
-
|
||||
- /* Check that the log does not contain any warning about the attached
|
||||
- * wl_callback proxy. */
|
||||
- log = maybe_map_file(client_log_fd, &log_len);
|
||||
- ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u",
|
||||
- wl_proxy_get_id((struct wl_proxy *) callback));
|
||||
- assert(ret > 0 && ret < (int)sizeof(callback_name) &&
|
||||
- "callback name creation failed (possibly truncated)");
|
||||
- assert(log == MAP_FAILED || strstr(log, callback_name) == NULL);
|
||||
- if (log != MAP_FAILED)
|
||||
- munmap(log, log_len);
|
||||
-
|
||||
- /* HACK: Directly free the memory of the wl_callback proxy to appease
|
||||
- * ASan. We would normally use wl_callback_destroy(), but since we have
|
||||
- * destroyed the associated wl_display, using this function would lead
|
||||
- * to memory errors. */
|
||||
- free(callback);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
dummy_bind(struct wl_client *client,
|
||||
void *data, uint32_t version, uint32_t id)
|
||||
@@ -585,15 +536,3 @@ TEST(queue_proxy_event_to_destroyed_queue)
|
||||
/* Check that the client aborted. */
|
||||
display_destroy_expect_signal(d, SIGABRT);
|
||||
}
|
||||
-
|
||||
-TEST(queue_destroy_default_with_attached_proxies)
|
||||
-{
|
||||
- struct display *d = display_create();
|
||||
-
|
||||
- test_set_timeout(2);
|
||||
-
|
||||
- client_create_noarg(d, client_test_queue_destroy_default_with_attached_proxies);
|
||||
- display_run(d);
|
||||
-
|
||||
- display_destroy(d);
|
||||
-}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
From ebc08059a18a66f0296e530351be830e8f3e7e53 Mon Sep 17 00:00:00 2001
|
||||
From: Wujian Sun <wujian.sun_1@nxp.com>
|
||||
Date: Wed, 29 Nov 2023 17:05:39 +0800
|
||||
Subject: [PATCH 2/4] Revert "client: Abort when trying to add an event to a
|
||||
destroyed queue"
|
||||
|
||||
This reverts commit d72f9007c36f2f8ad2dc26178545e8a7f5b993a0.
|
||||
Upstream-Status: Inappropriate [i.MX specific]
|
||||
---
|
||||
src/wayland-client.c | 5 ----
|
||||
tests/queue-test.c | 61 --------------------------------------------
|
||||
2 files changed, 66 deletions(-)
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index baebfa9..564e227 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -312,7 +312,6 @@ wl_event_queue_release(struct wl_event_queue *queue)
|
||||
wl_log(" %s@%u still attached\n",
|
||||
proxy->object.interface->name,
|
||||
proxy->object.id);
|
||||
- proxy->queue = NULL;
|
||||
wl_list_remove(&proxy->queue_link);
|
||||
wl_list_init(&proxy->queue_link);
|
||||
}
|
||||
@@ -542,7 +541,6 @@ proxy_destroy(struct wl_proxy *proxy)
|
||||
|
||||
proxy->flags |= WL_PROXY_FLAG_DESTROYED;
|
||||
|
||||
- proxy->queue = NULL;
|
||||
wl_list_remove(&proxy->queue_link);
|
||||
wl_list_init(&proxy->queue_link);
|
||||
|
||||
@@ -1567,9 +1565,6 @@ queue_event(struct wl_display *display, int len)
|
||||
else
|
||||
queue = proxy->queue;
|
||||
|
||||
- if (!queue)
|
||||
- wl_abort("Tried to add event to destroyed queue\n");
|
||||
-
|
||||
wl_list_insert(queue->event_list.prev, &closure->link);
|
||||
|
||||
return size;
|
||||
diff --git a/tests/queue-test.c b/tests/queue-test.c
|
||||
index 63abc19..f9254f7 100644
|
||||
--- a/tests/queue-test.c
|
||||
+++ b/tests/queue-test.c
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
-#include <signal.h>
|
||||
|
||||
#include "wayland-client.h"
|
||||
#include "wayland-server.h"
|
||||
@@ -385,43 +384,6 @@ client_test_queue_destroy_with_attached_proxies(void)
|
||||
wl_display_disconnect(display);
|
||||
}
|
||||
|
||||
-static void
|
||||
-client_test_queue_proxy_event_to_destroyed_queue(void)
|
||||
-{
|
||||
- struct wl_event_queue *queue;
|
||||
- struct wl_display *display;
|
||||
- struct wl_display *display_wrapper;
|
||||
- struct wl_callback *callback;
|
||||
-
|
||||
- display = wl_display_connect(NULL);
|
||||
- assert(display);
|
||||
-
|
||||
- /* Pretend we are in a separate thread where a thread-local queue is
|
||||
- * used. */
|
||||
- queue = wl_display_create_queue(display);
|
||||
- assert(queue);
|
||||
-
|
||||
- /* Create a sync dispatching events on the thread-local queue. */
|
||||
- display_wrapper = wl_proxy_create_wrapper(display);
|
||||
- assert(display_wrapper);
|
||||
- wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
|
||||
- callback = wl_display_sync(display_wrapper);
|
||||
- wl_proxy_wrapper_destroy(display_wrapper);
|
||||
- assert(callback != NULL);
|
||||
- wl_display_flush(display);
|
||||
-
|
||||
- /* Destroy the queue before the attached object. */
|
||||
- wl_event_queue_destroy(queue);
|
||||
-
|
||||
- /* During this roundtrip we should receive the done event on 'callback',
|
||||
- * try to queue it to the destroyed queue, and abort. */
|
||||
- wl_display_roundtrip(display);
|
||||
-
|
||||
- wl_callback_destroy(callback);
|
||||
-
|
||||
- wl_display_disconnect(display);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
dummy_bind(struct wl_client *client,
|
||||
void *data, uint32_t version, uint32_t id)
|
||||
@@ -513,26 +475,3 @@ TEST(queue_destroy_with_attached_proxies)
|
||||
|
||||
display_destroy(d);
|
||||
}
|
||||
-
|
||||
-TEST(queue_proxy_event_to_destroyed_queue)
|
||||
-{
|
||||
- struct display *d = display_create();
|
||||
- struct client_info *ci;
|
||||
- char *client_log;
|
||||
- size_t client_log_len;
|
||||
-
|
||||
- test_set_timeout(2);
|
||||
-
|
||||
- ci = client_create_noarg(d, client_test_queue_proxy_event_to_destroyed_queue);
|
||||
- display_run(d);
|
||||
-
|
||||
- /* Check that the final line in the log mentions the expected reason
|
||||
- * for the abort. */
|
||||
- client_log = map_file(ci->log_fd, &client_log_len);
|
||||
- assert(!strcmp(last_line_of(client_log),
|
||||
- "Tried to add event to destroyed queue\n"));
|
||||
- munmap(client_log, client_log_len);
|
||||
-
|
||||
- /* Check that the client aborted. */
|
||||
- display_destroy_expect_signal(d, SIGABRT);
|
||||
-}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
From 629b02dfa53ed6dc19378853b6f2ca3a308e30fe Mon Sep 17 00:00:00 2001
|
||||
From: Wujian Sun <wujian.sun_1@nxp.com>
|
||||
Date: Wed, 29 Nov 2023 17:05:59 +0800
|
||||
Subject: [PATCH 3/4] Revert "client: Warn when a queue is destroyed with
|
||||
attached proxies"
|
||||
|
||||
This reverts commit 0ba650202e742b23150054cf0740168cd529b010.
|
||||
Upstream-Status: Inappropriate [i.MX specific]
|
||||
---
|
||||
src/wayland-client.c | 16 --------
|
||||
tests/queue-test.c | 93 --------------------------------------------
|
||||
2 files changed, 109 deletions(-)
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index 564e227..8c897d4 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -301,22 +301,6 @@ wl_event_queue_release(struct wl_event_queue *queue)
|
||||
{
|
||||
struct wl_closure *closure;
|
||||
|
||||
- if (!wl_list_empty(&queue->proxy_list)) {
|
||||
- struct wl_proxy *proxy, *tmp;
|
||||
-
|
||||
- wl_log("warning: queue %p destroyed while proxies still "
|
||||
- "attached:\n", queue);
|
||||
-
|
||||
- wl_list_for_each_safe(proxy, tmp, &queue->proxy_list,
|
||||
- queue_link) {
|
||||
- wl_log(" %s@%u still attached\n",
|
||||
- proxy->object.interface->name,
|
||||
- proxy->object.id);
|
||||
- wl_list_remove(&proxy->queue_link);
|
||||
- wl_list_init(&proxy->queue_link);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
while (!wl_list_empty(&queue->event_list)) {
|
||||
closure = wl_container_of(queue->event_list.next,
|
||||
closure, link);
|
||||
diff --git a/tests/queue-test.c b/tests/queue-test.c
|
||||
index f9254f7..86a3602 100644
|
||||
--- a/tests/queue-test.c
|
||||
+++ b/tests/queue-test.c
|
||||
@@ -23,14 +23,11 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
-#define _GNU_SOURCE /* For memrchr */
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
-#include <string.h>
|
||||
#include <unistd.h>
|
||||
-#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
@@ -306,84 +303,6 @@ client_test_queue_set_queue_race(void)
|
||||
wl_display_disconnect(display);
|
||||
}
|
||||
|
||||
-static char *
|
||||
-map_file(int fd, size_t *len)
|
||||
-{
|
||||
- char *data;
|
||||
-
|
||||
- *len = lseek(fd, 0, SEEK_END);
|
||||
- data = mmap(0, *len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
- assert(data != MAP_FAILED && "Failed to mmap file");
|
||||
-
|
||||
- return data;
|
||||
-}
|
||||
-
|
||||
-static char *
|
||||
-last_line_of(char *s)
|
||||
-{
|
||||
- size_t len = strlen(s);
|
||||
- char *last;
|
||||
-
|
||||
- last = memrchr(s, '\n', len);
|
||||
- /* If we found a newline at end of string, find the previous one. */
|
||||
- if (last && last[1] == 0)
|
||||
- last = memrchr(s, '\n', len - 1);
|
||||
- /* If we have a newline, the last line starts after the newline.
|
||||
- * Otherwise, the whole string is the last line. */
|
||||
- if (last)
|
||||
- last += 1;
|
||||
- else
|
||||
- last = s;
|
||||
-
|
||||
- return last;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-client_test_queue_destroy_with_attached_proxies(void)
|
||||
-{
|
||||
- struct wl_event_queue *queue;
|
||||
- struct wl_display *display;
|
||||
- struct wl_display *display_wrapper;
|
||||
- struct wl_callback *callback;
|
||||
- char *log;
|
||||
- size_t log_len;
|
||||
- char callback_name[24];
|
||||
- int ret;
|
||||
-
|
||||
- display = wl_display_connect(NULL);
|
||||
- assert(display);
|
||||
-
|
||||
- /* Pretend we are in a separate thread where a thread-local queue is
|
||||
- * used. */
|
||||
- queue = wl_display_create_queue(display);
|
||||
- assert(queue);
|
||||
-
|
||||
- /* Create a sync dispatching events on the thread-local queue. */
|
||||
- display_wrapper = wl_proxy_create_wrapper(display);
|
||||
- assert(display_wrapper);
|
||||
- wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
|
||||
- callback = wl_display_sync(display_wrapper);
|
||||
- wl_proxy_wrapper_destroy(display_wrapper);
|
||||
- assert(callback != NULL);
|
||||
-
|
||||
- /* Destroy the queue before the attached object. */
|
||||
- wl_event_queue_destroy(queue);
|
||||
-
|
||||
- /* Check that the log contains some information about the attached
|
||||
- * wl_callback proxy. */
|
||||
- log = map_file(client_log_fd, &log_len);
|
||||
- ret = snprintf(callback_name, sizeof(callback_name), "wl_callback@%u",
|
||||
- wl_proxy_get_id((struct wl_proxy *) callback));
|
||||
- assert(ret > 0 && ret < (int)sizeof(callback_name) &&
|
||||
- "callback name creation failed (possibly truncated)");
|
||||
- assert(strstr(last_line_of(log), callback_name));
|
||||
- munmap(log, log_len);
|
||||
-
|
||||
- wl_callback_destroy(callback);
|
||||
-
|
||||
- wl_display_disconnect(display);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
dummy_bind(struct wl_client *client,
|
||||
void *data, uint32_t version, uint32_t id)
|
||||
@@ -463,15 +382,3 @@ TEST(queue_set_queue_race)
|
||||
|
||||
display_destroy(d);
|
||||
}
|
||||
-
|
||||
-TEST(queue_destroy_with_attached_proxies)
|
||||
-{
|
||||
- struct display *d = display_create();
|
||||
-
|
||||
- test_set_timeout(2);
|
||||
-
|
||||
- client_create_noarg(d, client_test_queue_destroy_with_attached_proxies);
|
||||
- display_run(d);
|
||||
-
|
||||
- display_destroy(d);
|
||||
-}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
From 5780ff48cd5e40c2669f3cd94653ab7f850d7a98 Mon Sep 17 00:00:00 2001
|
||||
From: Wujian Sun <wujian.sun_1@nxp.com>
|
||||
Date: Wed, 29 Nov 2023 17:06:22 +0800
|
||||
Subject: [PATCH 4/4] Revert "client: Track the proxies attached to a queue"
|
||||
|
||||
This reverts commit 674145dc3f621e5a3673714c7527d0e1c5336ab1.
|
||||
Upstream-Status: Inappropriate [i.MX specific]
|
||||
---
|
||||
src/wayland-client.c | 22 ----------------------
|
||||
1 file changed, 22 deletions(-)
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index 8c897d4..b57bfe9 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -70,12 +70,10 @@ struct wl_proxy {
|
||||
wl_dispatcher_func_t dispatcher;
|
||||
uint32_t version;
|
||||
const char * const *tag;
|
||||
- struct wl_list queue_link; /**< in struct wl_event_queue::proxy_list */
|
||||
};
|
||||
|
||||
struct wl_event_queue {
|
||||
struct wl_list event_list;
|
||||
- struct wl_list proxy_list; /**< struct wl_proxy::queue_link */
|
||||
struct wl_display *display;
|
||||
};
|
||||
|
||||
@@ -223,7 +221,6 @@ static void
|
||||
wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
|
||||
{
|
||||
wl_list_init(&queue->event_list);
|
||||
- wl_list_init(&queue->proxy_list);
|
||||
queue->display = display;
|
||||
}
|
||||
|
||||
@@ -438,8 +435,6 @@ proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link);
|
||||
-
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@@ -499,8 +494,6 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link);
|
||||
-
|
||||
return proxy;
|
||||
}
|
||||
|
||||
@@ -525,9 +518,6 @@ proxy_destroy(struct wl_proxy *proxy)
|
||||
|
||||
proxy->flags |= WL_PROXY_FLAG_DESTROYED;
|
||||
|
||||
- wl_list_remove(&proxy->queue_link);
|
||||
- wl_list_init(&proxy->queue_link);
|
||||
-
|
||||
wl_proxy_unref(proxy);
|
||||
}
|
||||
|
||||
@@ -2346,8 +2336,6 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
|
||||
{
|
||||
pthread_mutex_lock(&proxy->display->mutex);
|
||||
|
||||
- wl_list_remove(&proxy->queue_link);
|
||||
-
|
||||
if (queue) {
|
||||
assert(proxy->display == queue->display);
|
||||
proxy->queue = queue;
|
||||
@@ -2355,8 +2343,6 @@ wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
|
||||
proxy->queue = &proxy->display->default_queue;
|
||||
}
|
||||
|
||||
- wl_list_insert(&proxy->queue->proxy_list, &proxy->queue_link);
|
||||
-
|
||||
pthread_mutex_unlock(&proxy->display->mutex);
|
||||
}
|
||||
|
||||
@@ -2428,8 +2414,6 @@ wl_proxy_create_wrapper(void *proxy)
|
||||
wrapper->flags = WL_PROXY_FLAG_WRAPPER;
|
||||
wrapper->refcount = 1;
|
||||
|
||||
- wl_list_insert(&wrapper->queue->proxy_list, &wrapper->queue_link);
|
||||
-
|
||||
pthread_mutex_unlock(&wrapped_proxy->display->mutex);
|
||||
|
||||
return wrapper;
|
||||
@@ -2451,12 +2435,6 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
|
||||
|
||||
assert(wrapper->refcount == 1);
|
||||
|
||||
- pthread_mutex_lock(&wrapper->display->mutex);
|
||||
-
|
||||
- wl_list_remove(&wrapper->queue_link);
|
||||
-
|
||||
- pthread_mutex_unlock(&wrapper->display->mutex);
|
||||
-
|
||||
free(wrapper);
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,795 @@
|
|||
From 223d1f32861e21bf9827b813659fbe46c97d8e66 Mon Sep 17 00:00:00 2001
|
||||
From: Erik Chen <erikchen@chromium.org>
|
||||
Date: Thu, 20 Oct 2022 00:06:01 +0000
|
||||
Subject: [PATCH 1/5] Apply WIP CL from upstream wayland
|
||||
|
||||
This CL provides the capability of dynamically modifying the buffer size.
|
||||
https://gitlab.freedesktop.org/wayland/wayland/-/commit/0bfcd4c4bef0ddb555c0e9f07cd3ceff81a33313
|
||||
|
||||
Note that I am not the author. This CL has been reviewed upstream.
|
||||
|
||||
Bug: 1342356
|
||||
Change-Id: I24f90fb31248a52aa97f1813a5ff9b30157aa350
|
||||
Upstream-Status: Pending
|
||||
---
|
||||
src/connection.c | 303 ++++++++++++++++++++++++++++----------
|
||||
src/wayland-client.c | 2 +-
|
||||
src/wayland-private.h | 8 +-
|
||||
src/wayland-server-core.h | 7 +
|
||||
src/wayland-server.c | 63 +++++++-
|
||||
tests/connection-test.c | 46 +++++-
|
||||
tests/display-test.c | 5 +-
|
||||
tests/os-wrappers-test.c | 6 +-
|
||||
8 files changed, 350 insertions(+), 90 deletions(-)
|
||||
|
||||
diff --git a/src/connection.c b/src/connection.c
|
||||
index ceaeac1..bc6d730 100644
|
||||
--- a/src/connection.c
|
||||
+++ b/src/connection.c
|
||||
@@ -55,12 +55,12 @@ div_roundup(uint32_t n, size_t a)
|
||||
}
|
||||
|
||||
struct wl_ring_buffer {
|
||||
- char data[4096];
|
||||
- uint32_t head, tail;
|
||||
+ char *data;
|
||||
+ size_t head, tail;
|
||||
+ uint32_t size_bits;
|
||||
+ uint32_t max_size_bits; /* 0 for unlimited */
|
||||
};
|
||||
|
||||
-#define MASK(i) ((i) & 4095)
|
||||
-
|
||||
#define MAX_FDS_OUT 28
|
||||
#define CLEN (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
|
||||
|
||||
@@ -71,23 +71,27 @@ struct wl_connection {
|
||||
int want_flush;
|
||||
};
|
||||
|
||||
+static size_t
|
||||
+ring_buffer_space(const struct wl_ring_buffer *b) {
|
||||
+ return ((size_t)1) << b->size_bits;
|
||||
+}
|
||||
+
|
||||
+static size_t
|
||||
+ring_buffer_mask(const struct wl_ring_buffer *b, size_t i) {
|
||||
+ size_t m = (((size_t)1) << b->size_bits) - 1;
|
||||
+ return i & m;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
|
||||
{
|
||||
- uint32_t head, size;
|
||||
+ size_t head, size;
|
||||
|
||||
- if (count > sizeof(b->data)) {
|
||||
- wl_log("Data too big for buffer (%d > %d).\n",
|
||||
- count, sizeof(b->data));
|
||||
- errno = E2BIG;
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- head = MASK(b->head);
|
||||
- if (head + count <= sizeof b->data) {
|
||||
+ head = ring_buffer_mask(b, b->head);
|
||||
+ if (head + count <= ring_buffer_space(b)) {
|
||||
memcpy(b->data + head, data, count);
|
||||
} else {
|
||||
- size = sizeof b->data - head;
|
||||
+ size = ring_buffer_space(b) - head;
|
||||
memcpy(b->data + head, data, size);
|
||||
memcpy(b->data, (const char *) data + size, count - size);
|
||||
}
|
||||
@@ -100,21 +104,21 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
|
||||
static void
|
||||
ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
{
|
||||
- uint32_t head, tail;
|
||||
+ size_t head, tail;
|
||||
|
||||
- head = MASK(b->head);
|
||||
- tail = MASK(b->tail);
|
||||
+ head = ring_buffer_mask(b, b->head);
|
||||
+ tail = ring_buffer_mask(b, b->tail);
|
||||
if (head < tail) {
|
||||
iov[0].iov_base = b->data + head;
|
||||
iov[0].iov_len = tail - head;
|
||||
*count = 1;
|
||||
} else if (tail == 0) {
|
||||
iov[0].iov_base = b->data + head;
|
||||
- iov[0].iov_len = sizeof b->data - head;
|
||||
+ iov[0].iov_len = ring_buffer_space(b) - head;
|
||||
*count = 1;
|
||||
} else {
|
||||
iov[0].iov_base = b->data + head;
|
||||
- iov[0].iov_len = sizeof b->data - head;
|
||||
+ iov[0].iov_len = ring_buffer_space(b) - head;
|
||||
iov[1].iov_base = b->data;
|
||||
iov[1].iov_len = tail;
|
||||
*count = 2;
|
||||
@@ -124,21 +128,21 @@ ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
static void
|
||||
ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
{
|
||||
- uint32_t head, tail;
|
||||
+ size_t head, tail;
|
||||
|
||||
- head = MASK(b->head);
|
||||
- tail = MASK(b->tail);
|
||||
+ head = ring_buffer_mask(b, b->head);
|
||||
+ tail = ring_buffer_mask(b, b->tail);
|
||||
if (tail < head) {
|
||||
iov[0].iov_base = b->data + tail;
|
||||
iov[0].iov_len = head - tail;
|
||||
*count = 1;
|
||||
} else if (head == 0) {
|
||||
iov[0].iov_base = b->data + tail;
|
||||
- iov[0].iov_len = sizeof b->data - tail;
|
||||
+ iov[0].iov_len = ring_buffer_space(b) - tail;
|
||||
*count = 1;
|
||||
} else {
|
||||
iov[0].iov_base = b->data + tail;
|
||||
- iov[0].iov_len = sizeof b->data - tail;
|
||||
+ iov[0].iov_len = ring_buffer_space(b) - tail;
|
||||
iov[1].iov_base = b->data;
|
||||
iov[1].iov_len = head;
|
||||
*count = 2;
|
||||
@@ -148,26 +152,136 @@ ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
|
||||
static void
|
||||
ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
|
||||
{
|
||||
- uint32_t tail, size;
|
||||
+ size_t tail, size;
|
||||
|
||||
- tail = MASK(b->tail);
|
||||
- if (tail + count <= sizeof b->data) {
|
||||
+ tail = ring_buffer_mask(b, b->tail);
|
||||
+ if (tail + count <= ring_buffer_space(b)) {
|
||||
memcpy(data, b->data + tail, count);
|
||||
} else {
|
||||
- size = sizeof b->data - tail;
|
||||
+ size = ring_buffer_space(b) - tail;
|
||||
memcpy(data, b->data + tail, size);
|
||||
memcpy((char *) data + size, b->data, count - size);
|
||||
}
|
||||
}
|
||||
|
||||
-static uint32_t
|
||||
+static size_t
|
||||
ring_buffer_size(struct wl_ring_buffer *b)
|
||||
{
|
||||
return b->head - b->tail;
|
||||
}
|
||||
|
||||
+static uint32_t
|
||||
+get_max_size_bits_for_size(size_t buffer_size)
|
||||
+{
|
||||
+ uint32_t max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+
|
||||
+ /* buffer_size == 0 means unbound buffer size */
|
||||
+ if (buffer_size == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ do {
|
||||
+ if (buffer_size <= (((size_t)1) << max_size_bits))
|
||||
+ break;
|
||||
+ } while (max_size_bits++ < (8 * sizeof(size_t) - 1));
|
||||
+
|
||||
+ return max_size_bits;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+ring_buffer_allocate(struct wl_ring_buffer *b, size_t size_bits)
|
||||
+{
|
||||
+ char *new_data;
|
||||
+
|
||||
+ new_data = calloc(((size_t)1) << size_bits, 1);
|
||||
+ if (!new_data) {
|
||||
+ errno = ENOMEM;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ring_buffer_copy(b, new_data, ring_buffer_size(b));
|
||||
+ free(b->data);
|
||||
+ b->data = new_data;
|
||||
+ b->size_bits = size_bits;
|
||||
+ b->head = ring_buffer_size(b);
|
||||
+ b->tail = 0;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static size_t
|
||||
+ring_buffer_get_bits_for_size(struct wl_ring_buffer *b, size_t count)
|
||||
+{
|
||||
+ size_t net_size = ring_buffer_size(b) + count;
|
||||
+ size_t max_size_bits = get_max_size_bits_for_size(net_size);
|
||||
+
|
||||
+ if (max_size_bits < WL_BUFFER_DEFAULT_SIZE_POT)
|
||||
+ max_size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+
|
||||
+ if (b->max_size_bits > 0 && max_size_bits > b->max_size_bits)
|
||||
+ max_size_bits = b->max_size_bits;
|
||||
+
|
||||
+ return max_size_bits;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+ring_buffer_check_space(struct wl_ring_buffer *b, size_t count)
|
||||
+{
|
||||
+ if (ring_buffer_size(b) + count > ring_buffer_space(b)) {
|
||||
+ wl_log("Data too big for buffer (%d + %zd > %zd).\n",
|
||||
+ ring_buffer_size(b), count, ring_buffer_space(b));
|
||||
+ errno = E2BIG;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+ring_buffer_ensure_space(struct wl_ring_buffer *b, size_t count)
|
||||
+{
|
||||
+ size_t size_bits = ring_buffer_get_bits_for_size(b, count);
|
||||
+ size_t net_size = ring_buffer_size(b) + count;
|
||||
+
|
||||
+ if (b->data == NULL)
|
||||
+ return ring_buffer_allocate(b, size_bits);
|
||||
+
|
||||
+ /* Do not shrink (reallocate) if net size won't fit */
|
||||
+ if (net_size >= (((size_t)1) << size_bits) || b->size_bits == size_bits)
|
||||
+ return ring_buffer_check_space(b, count);
|
||||
+
|
||||
+ if (ring_buffer_allocate(b, size_bits) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return ring_buffer_check_space(b, count);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+wl_connection_set_max_buffer_size(struct wl_connection *connection,
|
||||
+ size_t max_buffer_size)
|
||||
+{
|
||||
+ uint32_t max_size_bits;
|
||||
+
|
||||
+ max_size_bits = get_max_size_bits_for_size(max_buffer_size);
|
||||
+
|
||||
+ connection->fds_in.size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+ connection->fds_in.max_size_bits = max_size_bits;
|
||||
+ ring_buffer_ensure_space(&connection->fds_in, 0);
|
||||
+
|
||||
+ connection->fds_out.size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+ connection->fds_out.max_size_bits = max_size_bits;
|
||||
+ ring_buffer_ensure_space(&connection->fds_out, 0);
|
||||
+
|
||||
+ connection->in.size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+ connection->in.max_size_bits = max_size_bits;
|
||||
+ ring_buffer_ensure_space(&connection->in, 0);
|
||||
+
|
||||
+ connection->out.size_bits = WL_BUFFER_DEFAULT_SIZE_POT;
|
||||
+ connection->out.max_size_bits = max_size_bits;
|
||||
+ ring_buffer_ensure_space(&connection->out, 0);
|
||||
+}
|
||||
+
|
||||
struct wl_connection *
|
||||
-wl_connection_create(int fd)
|
||||
+wl_connection_create(int fd, size_t max_buffer_size)
|
||||
{
|
||||
struct wl_connection *connection;
|
||||
|
||||
@@ -175,6 +289,8 @@ wl_connection_create(int fd)
|
||||
if (connection == NULL)
|
||||
return NULL;
|
||||
|
||||
+ wl_connection_set_max_buffer_size(connection, max_buffer_size);
|
||||
+
|
||||
connection->fd = fd;
|
||||
|
||||
return connection;
|
||||
@@ -183,20 +299,28 @@ wl_connection_create(int fd)
|
||||
static void
|
||||
close_fds(struct wl_ring_buffer *buffer, int max)
|
||||
{
|
||||
- int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
|
||||
- size_t size;
|
||||
+ size_t size, tail, space;
|
||||
+ int32_t i, count, *p;
|
||||
|
||||
size = ring_buffer_size(buffer);
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
- ring_buffer_copy(buffer, fds, size);
|
||||
- count = size / sizeof fds[0];
|
||||
+ count = size / sizeof(int32_t);
|
||||
if (max > 0 && max < count)
|
||||
count = max;
|
||||
- size = count * sizeof fds[0];
|
||||
- for (i = 0; i < count; i++)
|
||||
- close(fds[i]);
|
||||
+
|
||||
+ tail = ring_buffer_mask(buffer, buffer->tail);
|
||||
+ space = ring_buffer_space(buffer);
|
||||
+
|
||||
+ p = (int32_t *) (buffer->data + tail);
|
||||
+ for (i = 0; i < count; i++) {
|
||||
+ if (p >= (int32_t *) (buffer->data + space))
|
||||
+ p = (int32_t *) buffer->data;
|
||||
+ close(*p++);
|
||||
+ }
|
||||
+
|
||||
+ size = count * sizeof(int32_t);
|
||||
buffer->tail += size;
|
||||
}
|
||||
|
||||
@@ -213,6 +337,10 @@ wl_connection_destroy(struct wl_connection *connection)
|
||||
|
||||
close_fds(&connection->fds_out, -1);
|
||||
close_fds(&connection->fds_in, -1);
|
||||
+ free(connection->fds_in.data);
|
||||
+ free(connection->fds_out.data);
|
||||
+ free(connection->in.data);
|
||||
+ free(connection->out.data);
|
||||
free(connection);
|
||||
|
||||
return fd;
|
||||
@@ -256,7 +384,7 @@ static int
|
||||
decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cmsg;
|
||||
- size_t size, max, i;
|
||||
+ size_t size, i;
|
||||
int overflow = 0;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
|
||||
@@ -266,8 +394,8 @@ decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
|
||||
continue;
|
||||
|
||||
size = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
- max = sizeof(buffer->data) - ring_buffer_size(buffer);
|
||||
- if (size > max || overflow) {
|
||||
+
|
||||
+ if (ring_buffer_ensure_space(buffer, size) < 0 || overflow) {
|
||||
overflow = 1;
|
||||
size /= sizeof(int32_t);
|
||||
for (i = 0; i < size; i++)
|
||||
@@ -293,17 +421,30 @@ wl_connection_flush(struct wl_connection *connection)
|
||||
char cmsg[CLEN];
|
||||
int len = 0, count;
|
||||
size_t clen;
|
||||
- uint32_t tail;
|
||||
+ size_t tail;
|
||||
|
||||
if (!connection->want_flush)
|
||||
return 0;
|
||||
|
||||
tail = connection->out.tail;
|
||||
while (connection->out.head - connection->out.tail > 0) {
|
||||
- ring_buffer_get_iov(&connection->out, iov, &count);
|
||||
-
|
||||
build_cmsg(&connection->fds_out, cmsg, &clen);
|
||||
|
||||
+ if (clen >= CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t))) {
|
||||
+ /* Send only a single byte, to ensure all FDs are sent
|
||||
+ * before the bytes are cleared out. This can fail to
|
||||
+ * clear the FDs first if individual messages are allowed to
|
||||
+ * have 8*28 = 224 fds. */
|
||||
+ iov[0].iov_base = connection->out.data +
|
||||
+ ring_buffer_mask(&connection->out, connection->out.tail);
|
||||
+ iov[0].iov_len = 1;
|
||||
+ count = 1;
|
||||
+ } else {
|
||||
+ ring_buffer_get_iov(&connection->out, iov, &count);
|
||||
+ }
|
||||
+
|
||||
+ msg.msg_name = NULL;
|
||||
+ msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = (clen > 0) ? cmsg : NULL;
|
||||
@@ -341,49 +482,49 @@ wl_connection_read(struct wl_connection *connection)
|
||||
char cmsg[CLEN];
|
||||
int len, count, ret;
|
||||
|
||||
- if (ring_buffer_size(&connection->in) >= sizeof(connection->in.data)) {
|
||||
- errno = EOVERFLOW;
|
||||
- return -1;
|
||||
- }
|
||||
+ while (1) {
|
||||
+ int data_size = ring_buffer_size(&connection->in);
|
||||
+ size_t size_bits = ring_buffer_get_bits_for_size(&connection->in, 1);
|
||||
|
||||
- ring_buffer_put_iov(&connection->in, iov, &count);
|
||||
+ // stop once we've read the max buffer size
|
||||
+ if (data_size >= (1 << size_bits))
|
||||
+ return data_size;
|
||||
+ if (ring_buffer_ensure_space(&connection->in, 1) < 0)
|
||||
+ return -1;
|
||||
|
||||
- msg.msg_name = NULL;
|
||||
- msg.msg_namelen = 0;
|
||||
- msg.msg_iov = iov;
|
||||
- msg.msg_iovlen = count;
|
||||
- msg.msg_control = cmsg;
|
||||
- msg.msg_controllen = sizeof cmsg;
|
||||
- msg.msg_flags = 0;
|
||||
+ ring_buffer_put_iov(&connection->in, iov, &count);
|
||||
|
||||
- do {
|
||||
- len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
|
||||
- } while (len < 0 && errno == EINTR);
|
||||
+ msg.msg_name = NULL;
|
||||
+ msg.msg_namelen = 0;
|
||||
+ msg.msg_iov = iov;
|
||||
+ msg.msg_iovlen = count;
|
||||
+ msg.msg_control = cmsg;
|
||||
+ msg.msg_controllen = sizeof cmsg;
|
||||
+ msg.msg_flags = 0;
|
||||
|
||||
- if (len <= 0)
|
||||
- return len;
|
||||
+ do {
|
||||
+ len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
|
||||
+ } while (len < 0 && errno == EINTR);
|
||||
|
||||
- ret = decode_cmsg(&connection->fds_in, &msg);
|
||||
- if (ret)
|
||||
- return -1;
|
||||
+ if (len < 0 && errno != EAGAIN) {
|
||||
+ return -1;
|
||||
+ } else if (len <= 0) {
|
||||
+ return (data_size > 0) ? data_size : len;
|
||||
+ }
|
||||
|
||||
- connection->in.head += len;
|
||||
+ ret = decode_cmsg(&connection->fds_in, &msg);
|
||||
+ if (ret)
|
||||
+ return -1;
|
||||
|
||||
- return wl_connection_pending_input(connection);
|
||||
+ connection->in.head += len;
|
||||
+ }
|
||||
}
|
||||
|
||||
int
|
||||
wl_connection_write(struct wl_connection *connection,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
- if (connection->out.head - connection->out.tail +
|
||||
- count > ARRAY_LENGTH(connection->out.data)) {
|
||||
- connection->want_flush = 1;
|
||||
- if (wl_connection_flush(connection) < 0)
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- if (ring_buffer_put(&connection->out, data, count) < 0)
|
||||
+ if (wl_connection_queue(connection, data, count) < 0)
|
||||
return -1;
|
||||
|
||||
connection->want_flush = 1;
|
||||
@@ -396,12 +537,15 @@ wl_connection_queue(struct wl_connection *connection,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
if (connection->out.head - connection->out.tail +
|
||||
- count > ARRAY_LENGTH(connection->out.data)) {
|
||||
+ count > WL_BUFFER_DEFAULT_MAX_SIZE) {
|
||||
connection->want_flush = 1;
|
||||
- if (wl_connection_flush(connection) < 0)
|
||||
+ if (wl_connection_flush(connection) < 0 && errno != EAGAIN)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ if (ring_buffer_ensure_space(&connection->out, count) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
return ring_buffer_put(&connection->out, data, count);
|
||||
}
|
||||
|
||||
@@ -427,12 +571,15 @@ wl_connection_get_fd(struct wl_connection *connection)
|
||||
static int
|
||||
wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
|
||||
{
|
||||
- if (ring_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
|
||||
+ if (ring_buffer_size(&connection->fds_out) >= MAX_FDS_OUT * sizeof fd) {
|
||||
connection->want_flush = 1;
|
||||
- if (wl_connection_flush(connection) < 0)
|
||||
+ if (wl_connection_flush(connection) < 0 && errno != EAGAIN)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+ if (ring_buffer_ensure_space(&connection->fds_out, sizeof fd) < 0)
|
||||
+ return -1;
|
||||
+
|
||||
return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
|
||||
}
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index b57bfe9..895d7b8 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -1198,7 +1198,7 @@ wl_display_connect_to_fd(int fd)
|
||||
*/
|
||||
display->proxy.version = 0;
|
||||
|
||||
- display->connection = wl_connection_create(display->fd);
|
||||
+ display->connection = wl_connection_create(display->fd, 0);
|
||||
if (display->connection == NULL)
|
||||
goto err_connection;
|
||||
|
||||
diff --git a/src/wayland-private.h b/src/wayland-private.h
|
||||
index 9274f1b..a3a5032 100644
|
||||
--- a/src/wayland-private.h
|
||||
+++ b/src/wayland-private.h
|
||||
@@ -47,6 +47,8 @@
|
||||
#define WL_SERVER_ID_START 0xff000000
|
||||
#define WL_MAP_MAX_OBJECTS 0x00f00000
|
||||
#define WL_CLOSURE_MAX_ARGS 20
|
||||
+#define WL_BUFFER_DEFAULT_SIZE_POT 12
|
||||
+#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT)
|
||||
|
||||
struct wl_object {
|
||||
const struct wl_interface *interface;
|
||||
@@ -106,7 +108,7 @@ void
|
||||
wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
|
||||
|
||||
struct wl_connection *
|
||||
-wl_connection_create(int fd);
|
||||
+wl_connection_create(int fd, size_t max_buffer_size);
|
||||
|
||||
int
|
||||
wl_connection_destroy(struct wl_connection *connection);
|
||||
@@ -237,4 +239,8 @@ zalloc(size_t s)
|
||||
void
|
||||
wl_connection_close_fds_in(struct wl_connection *connection, int max);
|
||||
|
||||
+void
|
||||
+wl_connection_set_max_buffer_size(struct wl_connection *connection,
|
||||
+ size_t max_buffer_size);
|
||||
+
|
||||
#endif
|
||||
diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
|
||||
index df95821..15ee498 100644
|
||||
--- a/src/wayland-server-core.h
|
||||
+++ b/src/wayland-server-core.h
|
||||
@@ -217,6 +217,10 @@ wl_display_flush_clients(struct wl_display *display);
|
||||
void
|
||||
wl_display_destroy_clients(struct wl_display *display);
|
||||
|
||||
+void
|
||||
+wl_display_set_default_max_buffer_size(struct wl_display *display,
|
||||
+ size_t max_buffer_size);
|
||||
+
|
||||
struct wl_client;
|
||||
|
||||
typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
|
||||
@@ -365,6 +369,9 @@ wl_client_for_each_resource(struct wl_client *client,
|
||||
wl_client_for_each_resource_iterator_func_t iterator,
|
||||
void *user_data);
|
||||
|
||||
+void
|
||||
+wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size);
|
||||
+
|
||||
/** \class wl_listener
|
||||
*
|
||||
* \brief A single listener for Wayland signals
|
||||
diff --git a/src/wayland-server.c b/src/wayland-server.c
|
||||
index d51acc6..166a065 100644
|
||||
--- a/src/wayland-server.c
|
||||
+++ b/src/wayland-server.c
|
||||
@@ -110,6 +110,8 @@ struct wl_display {
|
||||
|
||||
int terminate_efd;
|
||||
struct wl_event_source *term_source;
|
||||
+
|
||||
+ size_t max_buffer_size;
|
||||
};
|
||||
|
||||
struct wl_global {
|
||||
@@ -538,7 +540,8 @@ wl_client_create(struct wl_display *display, int fd)
|
||||
&client->pid) != 0)
|
||||
goto err_source;
|
||||
|
||||
- client->connection = wl_connection_create(fd);
|
||||
+ client->connection = wl_connection_create(fd, display->max_buffer_size);
|
||||
+
|
||||
if (client->connection == NULL)
|
||||
goto err_source;
|
||||
|
||||
@@ -1144,6 +1147,7 @@ wl_display_create(void)
|
||||
|
||||
display->global_filter = NULL;
|
||||
display->global_filter_data = NULL;
|
||||
+ display->max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
|
||||
wl_array_init(&display->additional_shm_formats);
|
||||
|
||||
@@ -1550,6 +1554,36 @@ wl_display_destroy_clients(struct wl_display *display)
|
||||
}
|
||||
}
|
||||
|
||||
+/** Sets the default maximum size for connection buffers of new clients
|
||||
+ *
|
||||
+ * \param display The display object
|
||||
+ * \param max_buffer_size The default maximum size of the connection buffers
|
||||
+ *
|
||||
+ * This function sets the default size of the internal connection buffers for
|
||||
+ * new clients, it doesn't change the buffer size for existing wl_client.
|
||||
+ *
|
||||
+ * The connection buffer size of each existing wl_client can be adjusted using
|
||||
+ * wl_client_set_max_buffer_size().
|
||||
+ *
|
||||
+ * The actual size of the connection buffers is a power of two, the requested
|
||||
+ * \a max_buffer_size is therefore rounded up to the nearest power of two value.
|
||||
+ *
|
||||
+ * The minimum buffer size is 4096.
|
||||
+ *
|
||||
+ * \sa wl_client_set_max_buffer_size
|
||||
+ *
|
||||
+ * \memberof wl_display
|
||||
+ */
|
||||
+WL_EXPORT void
|
||||
+wl_display_set_default_max_buffer_size(struct wl_display *display,
|
||||
+ size_t max_buffer_size)
|
||||
+{
|
||||
+ if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE)
|
||||
+ max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
+
|
||||
+ display->max_buffer_size = max_buffer_size;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
socket_data(int fd, uint32_t mask, void *data)
|
||||
{
|
||||
@@ -2245,6 +2279,33 @@ wl_signal_emit_mutable(struct wl_signal *signal, void *data)
|
||||
wl_list_remove(&end.link);
|
||||
}
|
||||
|
||||
+/** Adjust the maximum size of the client connection buffers
|
||||
+ *
|
||||
+ * \param client The client object
|
||||
+ * \param max_buffer_size The maximum size of the connection buffers
|
||||
+ *
|
||||
+ * The actual size of the connection buffers is a power of two, the requested
|
||||
+ * \a max_buffer_size is therefore rounded up to the nearest power of two value.
|
||||
+ *
|
||||
+ * Lowering the maximum size may not take effect immediately if the current content
|
||||
+ * of the buffer does not fit within the new size limit.
|
||||
+ *
|
||||
+ * The minimum buffer size is 4096. The default buffers size can be set using
|
||||
+ * wl_display_set_default_max_buffer_size()
|
||||
+ *
|
||||
+ * \sa wl_display_set_default_max_buffer_size()
|
||||
+ *
|
||||
+ * \memberof wl_client
|
||||
+ */
|
||||
+WL_EXPORT void
|
||||
+wl_client_set_max_buffer_size(struct wl_client *client, size_t max_buffer_size)
|
||||
+{
|
||||
+ if (max_buffer_size < WL_BUFFER_DEFAULT_MAX_SIZE)
|
||||
+ max_buffer_size = WL_BUFFER_DEFAULT_MAX_SIZE;
|
||||
+
|
||||
+ wl_connection_set_max_buffer_size(client->connection, max_buffer_size);
|
||||
+}
|
||||
+
|
||||
/** \cond INTERNAL */
|
||||
|
||||
/** Initialize a wl_priv_signal object
|
||||
diff --git a/tests/connection-test.c b/tests/connection-test.c
|
||||
index 9762e0d..0c76045 100644
|
||||
--- a/tests/connection-test.c
|
||||
+++ b/tests/connection-test.c
|
||||
@@ -50,7 +50,7 @@ setup(int *s)
|
||||
|
||||
assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
|
||||
|
||||
- connection = wl_connection_create(s[0]);
|
||||
+ connection = wl_connection_create(s[0], WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(connection);
|
||||
|
||||
return connection;
|
||||
@@ -183,9 +183,11 @@ setup_marshal_data(struct marshal_data *data)
|
||||
{
|
||||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
- data->read_connection = wl_connection_create(data->s[0]);
|
||||
+ data->read_connection = wl_connection_create(data->s[0],
|
||||
+ WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->read_connection);
|
||||
- data->write_connection = wl_connection_create(data->s[1]);
|
||||
+ data->write_connection = wl_connection_create(data->s[1],
|
||||
+ WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->write_connection);
|
||||
}
|
||||
|
||||
@@ -277,6 +279,25 @@ expected_fail_marshal(int expected_error, const char *format, ...)
|
||||
assert(errno == expected_error);
|
||||
}
|
||||
|
||||
+static void
|
||||
+marshal_send(struct marshal_data *data, const char *format, ...)
|
||||
+{
|
||||
+ struct wl_closure *closure;
|
||||
+ static const uint32_t opcode = 4444;
|
||||
+ static struct wl_object sender = { NULL, NULL, 1234 };
|
||||
+ struct wl_message message = { "test", format, NULL };
|
||||
+ va_list ap;
|
||||
+
|
||||
+ va_start(ap, format);
|
||||
+ closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
|
||||
+ va_end(ap);
|
||||
+
|
||||
+ assert(closure);
|
||||
+ assert(wl_closure_send(closure, data->write_connection) == 0);
|
||||
+
|
||||
+ wl_closure_destroy(closure);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
expected_fail_marshal_send(struct marshal_data *data, int expected_error,
|
||||
const char *format, ...)
|
||||
@@ -644,6 +665,25 @@ TEST(connection_marshal_too_big)
|
||||
free(big_string);
|
||||
}
|
||||
|
||||
+TEST(connection_marshal_big_enough)
|
||||
+{
|
||||
+ struct marshal_data data;
|
||||
+ char *big_string = malloc(5000);
|
||||
+
|
||||
+ assert(big_string);
|
||||
+
|
||||
+ memset(big_string, ' ', 4999);
|
||||
+ big_string[4999] = '\0';
|
||||
+
|
||||
+ setup_marshal_data(&data);
|
||||
+ wl_connection_set_max_buffer_size(data.write_connection, 5120);
|
||||
+
|
||||
+ marshal_send(&data, "s", big_string);
|
||||
+
|
||||
+ release_marshal_data(&data);
|
||||
+ free(big_string);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
marshal_helper(const char *format, void *handler, ...)
|
||||
{
|
||||
diff --git a/tests/display-test.c b/tests/display-test.c
|
||||
index bcb3267..6fc136d 100644
|
||||
--- a/tests/display-test.c
|
||||
+++ b/tests/display-test.c
|
||||
@@ -1513,10 +1513,7 @@ send_overflow_client(void *data)
|
||||
/* Do not close the pipe file descriptors afterwards, because the leak
|
||||
* check verifies that the initial/final FD counts are the same */
|
||||
assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp));
|
||||
-
|
||||
- /* Expect an error */
|
||||
- fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err));
|
||||
- assert(err == EAGAIN);
|
||||
+ assert(err == 0);
|
||||
|
||||
client_disconnect_nocheck(c);
|
||||
}
|
||||
diff --git a/tests/os-wrappers-test.c b/tests/os-wrappers-test.c
|
||||
index 8d8c3ab..e65a5d6 100644
|
||||
--- a/tests/os-wrappers-test.c
|
||||
+++ b/tests/os-wrappers-test.c
|
||||
@@ -256,10 +256,12 @@ setup_marshal_data(struct marshal_data *data)
|
||||
assert(socketpair(AF_UNIX,
|
||||
SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
|
||||
|
||||
- data->read_connection = wl_connection_create(data->s[0]);
|
||||
+ data->read_connection = wl_connection_create(data->s[0],
|
||||
+ WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->read_connection);
|
||||
|
||||
- data->write_connection = wl_connection_create(data->s[1]);
|
||||
+ data->write_connection = wl_connection_create(data->s[1],
|
||||
+ WL_BUFFER_DEFAULT_MAX_SIZE);
|
||||
assert(data->write_connection);
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
From 191eeb6f2ed6429b16db053b45f0fa81df55329d Mon Sep 17 00:00:00 2001
|
||||
From: Erik Chen <erikchen@chromium.org>
|
||||
Date: Sun, 30 Oct 2022 23:31:57 +0000
|
||||
Subject: [PATCH 2/5] Set the default max buffer size to unbounded.
|
||||
|
||||
Bug: 1342356
|
||||
Change-Id: I6e6c353504d6817b9bf76bc7e8b24001d7957ad6
|
||||
Upstream-Status: Pending
|
||||
---
|
||||
src/connection.c | 2 +-
|
||||
src/wayland-private.h | 5 ++++-
|
||||
2 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/connection.c b/src/connection.c
|
||||
index bc6d730..2b3c7e4 100644
|
||||
--- a/src/connection.c
|
||||
+++ b/src/connection.c
|
||||
@@ -537,7 +537,7 @@ wl_connection_queue(struct wl_connection *connection,
|
||||
const void *data, size_t count)
|
||||
{
|
||||
if (connection->out.head - connection->out.tail +
|
||||
- count > WL_BUFFER_DEFAULT_MAX_SIZE) {
|
||||
+ count > WL_BUFFER_FLUSH_SIZE) {
|
||||
connection->want_flush = 1;
|
||||
if (wl_connection_flush(connection) < 0 && errno != EAGAIN)
|
||||
return -1;
|
||||
diff --git a/src/wayland-private.h b/src/wayland-private.h
|
||||
index a3a5032..1aafa2e 100644
|
||||
--- a/src/wayland-private.h
|
||||
+++ b/src/wayland-private.h
|
||||
@@ -48,7 +48,10 @@
|
||||
#define WL_MAP_MAX_OBJECTS 0x00f00000
|
||||
#define WL_CLOSURE_MAX_ARGS 20
|
||||
#define WL_BUFFER_DEFAULT_SIZE_POT 12
|
||||
-#define WL_BUFFER_DEFAULT_MAX_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT)
|
||||
+// 0 means unbounded.
|
||||
+#define WL_BUFFER_DEFAULT_MAX_SIZE 0
|
||||
+// The size at which queueing a request will also trigger a flush.
|
||||
+#define WL_BUFFER_FLUSH_SIZE (1 << WL_BUFFER_DEFAULT_SIZE_POT)
|
||||
|
||||
struct wl_object {
|
||||
const struct wl_interface *interface;
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
From 47a912b7a20d689da5a9e1fb848a616822de8b60 Mon Sep 17 00:00:00 2001
|
||||
From: Kramer Ge <fangzhoug@chromium.org>
|
||||
Date: Wed, 19 Jul 2023 14:46:56 -0400
|
||||
Subject: [PATCH 3/5] Log the object and methods when marshalling or sending
|
||||
fails.
|
||||
|
||||
The log that appears before a display_error will be captured as crash
|
||||
signature.
|
||||
|
||||
Bug: 1451333
|
||||
Change-Id: I06a0a1294c5431d0f8261e522aaa469e2c427725
|
||||
Upstream-Status: Pending
|
||||
---
|
||||
src/wayland-client.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/wayland-client.c b/src/wayland-client.c
|
||||
index 895d7b8..451c035 100644
|
||||
--- a/src/wayland-client.c
|
||||
+++ b/src/wayland-client.c
|
||||
@@ -848,7 +848,8 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
|
||||
|
||||
closure = wl_closure_marshal(&proxy->object, opcode, args, message);
|
||||
if (closure == NULL) {
|
||||
- wl_log("Error marshalling request: %s\n", strerror(errno));
|
||||
+ wl_log("Error marshalling request for %s.%s: %s\n",
|
||||
+ proxy->object.interface->name, message->name, strerror(errno));
|
||||
display_fatal_error(proxy->display, errno);
|
||||
goto err_unlock;
|
||||
}
|
||||
@@ -857,7 +858,8 @@ wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
|
||||
wl_closure_print(closure, &proxy->object, true, false, NULL);
|
||||
|
||||
if (wl_closure_send(closure, proxy->display->connection)) {
|
||||
- wl_log("Error sending request: %s\n", strerror(errno));
|
||||
+ wl_log("Error sending request for %s.%s: %s\n",
|
||||
+ proxy->object.interface->name, message->name, strerror(errno));
|
||||
display_fatal_error(proxy->display, errno);
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
From 3806c948b5e3af1e13383ce3b24b0cebfde0a721 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Lukaszewicz <tluk@chromium.org>
|
||||
Date: Fri, 21 Jul 2023 23:28:12 +0000
|
||||
Subject: [PATCH 4/5] Fix buffer resize crash
|
||||
|
||||
Currently chromium wayland clients can crash if a connection buffer
|
||||
(which is initialized at a capacity of 2^12) is asked to resize
|
||||
exactly at its resize threshold. This threshold is in steps of
|
||||
powers of 2.
|
||||
|
||||
Take net_size to be the size the connection buffer is required to
|
||||
support for the current outbound request queue.
|
||||
|
||||
This is crash due to certain parts of the code assuming that
|
||||
net_size can exactly match the capacity of the connection buffer,
|
||||
while other parts of the code assume the capacity of the buffer
|
||||
must exceed the net_size. The latter assumption is the root cause
|
||||
of the crash.
|
||||
|
||||
Specifically:
|
||||
1. ring_buffer_ensure_space() attempts to find the new buffer
|
||||
`size_bits` required to contain the new `net_size` of the
|
||||
request buffer [1]
|
||||
2. This eventually calls into get_max_size_bits_for_size()
|
||||
which finds the `size_bits` required for `net_size`[2]
|
||||
- This code assumes that `net_size <= 2^size_bits` in order
|
||||
to fit the data
|
||||
3. Back in ring_buffer_ensure_space() the `size_bits` returned
|
||||
is checked to ensure it can contain `net_size` and if a
|
||||
resize is needed.
|
||||
- This code assumes that `net_size < 2^size_bits` in order
|
||||
to fit the data [3]
|
||||
- If a resize is not needed, the buffer is checked
|
||||
whether it can hold `net_size` without resizing and a
|
||||
crash occurs [4]
|
||||
|
||||
The assumptions about buffer capacity differ in 2 and 3, and the
|
||||
assertion in 3 causes the crash in the associated bug. This only
|
||||
occurs when `net_size == 2^size_bits` which satisfies the condition
|
||||
in 2 but fails the condition in 3.
|
||||
|
||||
In Lacros code there were a set of users encountering this crash
|
||||
when buffers were being asked to resize when clients made the
|
||||
zwp_text_input_v1_set_surrounding_text() with large blocks of
|
||||
text (typically from a ssh session).
|
||||
|
||||
This CL enforces the requirement that the connection buffer must
|
||||
be greater than the net_size.
|
||||
|
||||
For more context see below.
|
||||
https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/188#note_2010874
|
||||
|
||||
[1] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#242
|
||||
|
||||
[2] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#183
|
||||
|
||||
[3] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#249
|
||||
|
||||
[4] https://chromium.googlesource.com/external/anongit.freedesktop.org/git/wayland/wayland/+/refs/heads/chromium_1_21_0/src/connection.c#229
|
||||
|
||||
Bug: 1451333
|
||||
Change-Id: I87853e3ff26c1d693f199fd0045fef796c3730c9
|
||||
Upstream-Status: Pending
|
||||
---
|
||||
src/connection.c | 2 +-
|
||||
tests/connection-test.c | 26 ++++++++++++++++++++++++++
|
||||
2 files changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/connection.c b/src/connection.c
|
||||
index 2b3c7e4..bea4714 100644
|
||||
--- a/src/connection.c
|
||||
+++ b/src/connection.c
|
||||
@@ -180,7 +180,7 @@ get_max_size_bits_for_size(size_t buffer_size)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
- if (buffer_size <= (((size_t)1) << max_size_bits))
|
||||
+ if (buffer_size < (((size_t)1) << max_size_bits))
|
||||
break;
|
||||
} while (max_size_bits++ < (8 * sizeof(size_t) - 1));
|
||||
|
||||
diff --git a/tests/connection-test.c b/tests/connection-test.c
|
||||
index 0c76045..7f64443 100644
|
||||
--- a/tests/connection-test.c
|
||||
+++ b/tests/connection-test.c
|
||||
@@ -684,6 +684,32 @@ TEST(connection_marshal_big_enough)
|
||||
free(big_string);
|
||||
}
|
||||
|
||||
+/* Ensures that buffers are resiable to accomodate requests for sizes at the
|
||||
+ * resize threshold (power of 2). Regression test for crbug.com/1451333. */
|
||||
+TEST(connection_marshal_resize_at_buffer_growth_threshold)
|
||||
+{
|
||||
+ /* A string of lenth 8178 requires a buffer size of exactly 2^13.
|
||||
+ * TODO(tluk): Determine a way to require a resize at 2^13 in a more robust
|
||||
+ * way */
|
||||
+ struct marshal_data data;
|
||||
+ const int kStrSize = 8178;
|
||||
+ char *big_string = malloc(kStrSize);
|
||||
+ assert(big_string);
|
||||
+
|
||||
+ memset(big_string, ' ', kStrSize-1);
|
||||
+ big_string[kStrSize-1] = '\0';
|
||||
+
|
||||
+ setup_marshal_data(&data);
|
||||
+
|
||||
+ /* Set the max size to 0 (unbounded). */
|
||||
+ wl_connection_set_max_buffer_size(data.write_connection, 0);
|
||||
+
|
||||
+ marshal_send(&data, "s", big_string);
|
||||
+
|
||||
+ release_marshal_data(&data);
|
||||
+ free(big_string);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
marshal_helper(const char *format, void *handler, ...)
|
||||
{
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From 603a8330853615f84674c0db86f65c1f1c671163 Mon Sep 17 00:00:00 2001
|
||||
From: David Benjamin <davidben@google.com>
|
||||
Date: Wed, 8 Nov 2023 11:51:40 -0500
|
||||
Subject: [PATCH 5/5] connection: avoid calling memcpy on NULL, 0
|
||||
|
||||
This imports
|
||||
https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/354 from
|
||||
upstream.
|
||||
|
||||
Bug: 1394755
|
||||
Change-Id: If8f495b6aa70871920de9f66a1f1600dce917a10
|
||||
Upstream-Status: Pending
|
||||
---
|
||||
src/connection.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/connection.c b/src/connection.c
|
||||
index bea4714..2233eb4 100644
|
||||
--- a/src/connection.c
|
||||
+++ b/src/connection.c
|
||||
@@ -87,6 +87,9 @@ ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
|
||||
{
|
||||
size_t head, size;
|
||||
|
||||
+ if (count == 0)
|
||||
+ return 0;
|
||||
+
|
||||
head = ring_buffer_mask(b, b->head);
|
||||
if (head + count <= ring_buffer_space(b)) {
|
||||
memcpy(b->data + head, data, count);
|
||||
@@ -154,6 +157,9 @@ ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
|
||||
{
|
||||
size_t tail, size;
|
||||
|
||||
+ if (count == 0)
|
||||
+ return;
|
||||
+
|
||||
tail = ring_buffer_mask(b, b->tail);
|
||||
if (tail + count <= ring_buffer_space(b)) {
|
||||
memcpy(data, b->data + tail, count);
|
||||
@@ -1333,7 +1339,8 @@ serialize_closure(struct wl_closure *closure, uint32_t *buffer,
|
||||
if (p + div_roundup(size, sizeof *p) > end)
|
||||
goto overflow;
|
||||
|
||||
- memcpy(p, closure->args[i].a->data, size);
|
||||
+ if (size != 0)
|
||||
+ memcpy(p, closure->args[i].a->data, size);
|
||||
p += div_roundup(size, sizeof *p);
|
||||
break;
|
||||
default:
|
||||
--
|
||||
2.17.1
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
SRC_URI:append:imxgpu:arm = " \
|
||||
file://0101-Revert-client-Do-not-warn-about-attached-proxies-on-.patch \
|
||||
file://0102-Revert-client-Abort-when-trying-to-add-an-event-to-a.patch \
|
||||
file://0103-Revert-client-Warn-when-a-queue-is-destroyed-with-at.patch \
|
||||
file://0104-Revert-client-Track-the-proxies-attached-to-a-queue.patch \
|
||||
file://0201-Apply-WIP-CL-from-upstream-wayland.patch \
|
||||
file://0202-Set-the-default-max-buffer-size-to-unbounded.patch \
|
||||
file://0203-Log-the-object-and-methods-when-marshalling-or-sendi.patch \
|
||||
file://0204-Fix-buffer-resize-crash.patch \
|
||||
file://0205-connection-avoid-calling-memcpy-on-NULL-0.patch \
|
||||
"
|
||||
Loading…
Reference in New Issue