aboutsummaryrefslogtreecommitdiffstats
path: root/src/wth-receiver-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wth-receiver-main.c')
-rw-r--r--src/wth-receiver-main.c69
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);