diff options
author | Marius Vlad <marius.vlad@collabora.com> | 2020-11-02 16:51:08 +0200 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2020-12-01 13:07:57 +0200 |
commit | 8fcbed84cfefcfe648584941587e6d06abf59c3e (patch) | |
tree | 4a370a19465e12543e74563fc136cf916554ca6f /src/wth-receiver-main.c | |
parent | 2373db4b31a646d4936f6700ecc2af857302444b (diff) |
wth-receiver: Handle events from the remote side and from the local compositor
With this, we fork and let the child deal with the gstreamer pipeline
while the parent is still able to process events from the transimtter.
Using blocking dispatching function will make the main loop be stuck in
processing events without being able to dispatch any handlers that might
be due to the requests from the transmistter side. So in order to allow
the mainloop (still) handle the events, we fork and let child deal with the
gstreamer pipeline.
Bug-AGL: SPEC-3675
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: I50e1d49b55849dc32f611538bad2ce1c676c9a97
Diffstat (limited to 'src/wth-receiver-main.c')
-rw-r--r-- | src/wth-receiver-main.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/wth-receiver-main.c b/src/wth-receiver-main.c index 8af8eda..54f73eb 100644 --- a/src/wth-receiver-main.c +++ b/src/wth-receiver-main.c @@ -34,6 +34,11 @@ *******************************************************************************/ #include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <unistd.h> + #include "wth-receiver-comm.h" #define MAX_EPOLL_WATCHES 2 @@ -150,6 +155,46 @@ listen_socket_handle_data(struct watch *w, uint32_t events) } } +static void +receiver_clean_up_child(pid_t pid, struct receiver *srv) +{ + struct client *client; + + /* client represents connection with the transmitter, so removing it + * from the client list isn't what need to happen. Mark the + * pid_destroying as to give it a chance for next time */ + wl_list_for_each(client, &srv->client_list, link) { + if (client->pid == pid) { + client->pid_destroying = false; + } + } +} + +static void +wait_for_children(struct receiver *srv, pid_t pid) +{ + pid_t w; + int status; + int options = WUNTRACED | WCONTINUED; + + do { + w = waitpid(pid, &status, options); + if (w == -1) { + fprintf(stderr, "err no children to wait for!\n"); + } + + if (WIFEXITED(status)) { + if (w > 0) { + receiver_clean_up_child(w, srv); + } + } else if (WIFSIGNALED(status)) { + // FIXME should remove the client here, and identify with the pid + } else if (WIFSTOPPED(status)) { + } else if (WIFCONTINUED(status)) { + } + + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); +} /** * receiver_mainloop * @@ -173,9 +218,33 @@ receiver_mainloop(struct receiver *srv) while (srv->running) { /* Run any idle tasks at this point. */ + bool should_wait_for_children = false; + struct client *client; receiver_flush_clients(srv); + wl_list_for_each(client, &srv->client_list, link) { + if (client->pid > 0 && client->pid_destroying) { + should_wait_for_children = true; + break; + } + } + + /* + * wait_for_children() will block and wait for children that + * died out/terminated correctly as the remote that end sent + * the destroy surface request. pid_destroying is the one that + * allows to make that distinction and will be set by the + * destroy surface handler. + * + * 'children' is just one. A new child will be started when the + * remote side sents a request to create a surface and will be + * killed in the handler that destroys the surface. + */ + if (should_wait_for_children) + wait_for_children(srv, client->pid); + + /* Wait for events or signals */ count = epoll_wait(srv->epoll_fd, ee, ARRAY_LENGTH(ee), -1); |