diff options
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); |