meta-digi/meta-digi-dey/dynamic-layers/freescale-layer/recipes-graphics/wayland/wayland/0201-Apply-WIP-CL-from-upst...

796 lines
23 KiB
Diff

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