This copies the contents of keymaps over the network for remote connections. Any future user of fd_static should Just Work too.
Signed-off-by: Derek Foreman <der...@osg.samsung.com> --- src/connection.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/wayland-private.h | 2 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/connection.c b/src/connection.c index 8a44806..c1f65a4 100644 --- a/src/connection.c +++ b/src/connection.c @@ -562,9 +562,12 @@ wl_closure_marshal(struct wl_object *sender, uint32_t opcode, } memcpy(closure->args, args, count * sizeof *args); + closure->n_remote_fds = 0; signature = message->signature; for (i = 0; i < count; i++) { + bool has_bulk = false; + signature = get_next_argument(signature, &arg); switch (arg.type) { @@ -592,12 +595,25 @@ wl_closure_marshal(struct wl_object *sender, uint32_t opcode, goto err_null; break; case 'H': + has_bulk = true; case 'h': fd = args[i].h; dup_fd = wl_os_dupfd_cloexec(fd, 0); if (dup_fd < 0) wl_abort("dup failed: %s\n", strerror(errno)); closure->args[i].h = dup_fd; + if (sender->remote && has_bulk) { + /* Dupe it again for sending its data later, + * the other dupe will be automatically closed + * on connection flush. + */ + dup_fd = wl_os_dupfd_cloexec(dup_fd, 0); + if (dup_fd < 0) + wl_abort("dup failed: %s\n", + strerror(errno)); + closure->remote_fds[closure->n_remote_fds] = dup_fd; + closure->n_remote_fds++; + } break; default: wl_abort("unhandled format code: '%c'\n", arg.type); @@ -640,7 +656,7 @@ wl_connection_demarshal(struct wl_connection *connection, const struct wl_message *message) { uint32_t *p, *next, *end, length, id; - int fd; + int fd, fdi; char *s; unsigned int i, count, num_arrays; const char *signature; @@ -664,6 +680,8 @@ wl_connection_demarshal(struct wl_connection *connection, return NULL; } + closure->n_remote_fds = 0; + array_extra = closure->extra; p = (uint32_t *)(closure->extra + num_arrays); end = p + size / sizeof *p; @@ -674,6 +692,7 @@ wl_connection_demarshal(struct wl_connection *connection, signature = message->signature; for (i = 0; i < count; i++) { + bool has_bulk = false; signature = get_next_argument(signature, &arg); if (arg.type != 'h' && p + 1 > end) { @@ -779,7 +798,16 @@ wl_connection_demarshal(struct wl_connection *connection, p = next; break; case 'H': + has_bulk = true; case 'h': + if (connection->remote) { + closure->args[i].h = wl_os_create_anonymous_file(0); + if (has_bulk) { + closure->remote_fds[closure->n_remote_fds] = closure->args[i].h; + closure->n_remote_fds++; + } + break; + } if (connection->fds_in.tail == connection->fds_in.head) { wl_log("file descriptor expected, " "object (%d), message %s(%s)\n", @@ -804,6 +832,11 @@ wl_connection_demarshal(struct wl_connection *connection, wl_connection_consume(connection, size); + for (fdi = 0; fdi < closure->n_remote_fds; fdi++) + wl_connection_get_bulk_data(connection, closure->remote_fds[fdi]); + + /* we don't want to clean them up in destroy... */ + closure->n_remote_fds = 0; return closure; err: @@ -1215,6 +1248,7 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) uint32_t buffer_size; uint32_t *buffer; int result; + int i; if (copy_fds_to_connection(closure, connection)) return -1; @@ -1233,6 +1267,20 @@ wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) result = wl_connection_write(connection, buffer, size); free(buffer); + if (result < 0 || !closure->n_remote_fds) + return result; + + connection->want_flush = 1; + wl_connection_flush(connection); + + for (i = 0; i < closure->n_remote_fds; i++) { + result = wl_connection_put_bulk_data(connection, + closure->remote_fds[i]); + + if (result < 0) + break; + } + return result; } @@ -1261,6 +1309,11 @@ wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection) result = wl_connection_queue(connection, buffer, size); free(buffer); + if (closure->n_remote_fds) { + wl_log("Unable to queue closure with remote fds\n"); + return -1; + } + return result; } @@ -1335,5 +1388,10 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) void wl_closure_destroy(struct wl_closure *closure) { + int i; + + for (i = 0; i < closure->n_remote_fds; i++) + close(closure->remote_fds[i]); + free(closure); } diff --git a/src/wayland-private.h b/src/wayland-private.h index be41e83..f5d6100 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -150,6 +150,8 @@ struct wl_closure { uint32_t opcode; uint32_t sender_id; union wl_argument args[WL_CLOSURE_MAX_ARGS]; + int n_remote_fds; + int remote_fds[WL_CLOSURE_MAX_ARGS]; struct wl_list link; struct wl_proxy *proxy; struct wl_array extra[0]; -- 2.7.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel