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 | |
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
-rw-r--r-- | include/wth-receiver-comm.h | 4 | ||||
-rw-r--r-- | src/wth-receiver-comm.c | 60 | ||||
-rw-r--r-- | src/wth-receiver-gst-shm.c | 10 | ||||
-rw-r--r-- | src/wth-receiver-main.c | 69 | ||||
-rw-r--r-- | src/wth-receiver-seat.c | 9 |
5 files changed, 121 insertions, 31 deletions
diff --git a/include/wth-receiver-comm.h b/include/wth-receiver-comm.h index 4499053..fc6e6ae 100644 --- a/include/wth-receiver-comm.h +++ b/include/wth-receiver-comm.h @@ -131,6 +131,7 @@ struct ivisurface { struct wthp_callback *cb; struct wl_list link; /* struct client::surface_list */ struct surface *surf; + struct application_id *appid; }; /* wthp_ivi_application protocol object */ @@ -164,6 +165,9 @@ struct client { struct wl_list link; /* struct receiver::client_list */ struct receiver *receiver; + pid_t pid; + bool pid_destroying; + struct wth_connection *connection; struct watch conn_watch; diff --git a/src/wth-receiver-comm.c b/src/wth-receiver-comm.c index e6c0266..0527ecd 100644 --- a/src/wth-receiver-comm.c +++ b/src/wth-receiver-comm.c @@ -34,12 +34,16 @@ ** ** ** ** *******************************************************************************/ +#include <sys/types.h> +#include <signal.h> #include "wth-receiver-comm.h" #include "wth-receiver-surface.h" #include "wth-receiver-seat.h" #include "wth-receiver-buffer.h" +#include <waltham-util.h> + extern uint16_t tcp_port; extern const char *my_app_id; @@ -59,9 +63,17 @@ static void wthp_ivi_surface_destroy(struct wthp_ivi_surface * ivi_surface) { struct ivisurface *ivisurf = wth_object_get_user_data((struct wth_object *)ivi_surface); - - if (ivisurf->surf->ivi_app_id) - free(ivisurf->surf->ivi_app_id); + struct client *client = ivisurf->appid->client; + + if (client) { + client->pid_destroying = true; + fprintf(stdout, "client pid_destroying to true for client %p pid %d\n", + client, client->pid); + if (kill(client->pid, SIGINT) < 0) { + fprintf(stderr, "Failed to send SIGINT to child %d\n", + client->pid); + } + } free(ivisurf); } @@ -80,34 +92,42 @@ wthp_ivi_app_id_surface_create(struct wthp_ivi_app_id *ivi_application, struct wthp_surface * wthp_surface, struct wthp_ivi_surface *obj) { - struct surface *surface = wth_object_get_user_data((struct wth_object *)wthp_surface); - - /* we destroy it wthp_ivi_surface_implementation:: */ - if (my_app_id) { - surface->ivi_app_id = strdup(my_app_id); - surface->shm_window->app_id = surface->ivi_app_id; - } - - struct ivisurface *ivisurf; + struct surface *surface = + wth_object_get_user_data((struct wth_object *)wthp_surface); + struct application_id *appid = + wth_object_get_user_data((struct wth_object *) ivi_application); + pid_t cpid; - ivisurf = zalloc(sizeof *ivisurf); + struct ivisurface *ivisurf = zalloc(sizeof *ivisurf); if (!ivisurf) { return; } ivisurf->obj = obj; ivisurf->surf = surface; + ivisurf->appid = appid; wthp_ivi_surface_set_interface(obj, &wthp_ivi_surface_implementation, ivisurf); - if (my_app_id) - wth_receiver_weston_main(surface->shm_window, my_app_id, tcp_port); - else - wth_receiver_weston_main(surface->shm_window, app_id, tcp_port); + cpid = fork(); + if (cpid == -1) { + fprintf(stderr, "Failed to fork()\n"); + exit(EXIT_FAILURE); + } + + if (cpid == 0) { + if (my_app_id) + wth_receiver_weston_main(surface->shm_window, my_app_id, tcp_port); + else + wth_receiver_weston_main(surface->shm_window, app_id, tcp_port); + } else { + /* this is parent, in wthp_ivi_surface_destroy() we mark that the + * client should be waited for so wait4() will be blocked. + */ + appid->client->pid = cpid; + } - while (!surface->shm_window->ready) - usleep(1); } static const struct wthp_ivi_app_id_interface wthp_ivi_app_id_implementation = { @@ -387,6 +407,7 @@ client_create(struct receiver *srv, struct wth_connection *conn) disp = wth_connection_get_display(c->connection); wth_display_set_interface(disp, &display_implementation, c); + fprintf(stdout, "Client %p created\n", c); return c; } @@ -444,7 +465,6 @@ receiver_accept_client(struct receiver *srv) wth_error("Failed to accept a connection.\n"); return; } - client = client_create(srv, conn); if (!client) { wth_error("Failed client_create().\n"); diff --git a/src/wth-receiver-gst-shm.c b/src/wth-receiver-gst-shm.c index 2228d4f..50efe0b 100644 --- a/src/wth-receiver-gst-shm.c +++ b/src/wth-receiver-gst-shm.c @@ -815,7 +815,7 @@ wth_receiver_weston_main(struct window *window, const char *app_id, int port) memset(pipeline, 0x00, sizeof(pipeline)); snprintf(pipeline, sizeof(pipeline), pipe, port); - fprintf(stdout, "pipeline %s\n", pipeline); + fprintf(stdout, "Using pipeline %s\n", pipeline); /* parse the pipeline */ gstctx.pipeline = gst_parse_launch(pipeline, &gerror); @@ -836,7 +836,6 @@ wth_receiver_weston_main(struct window *window, const char *app_id, int port) while (running && ret != -1) ret = wl_display_dispatch(gstctx.display->display); - gst_element_set_state(gstctx.pipeline, GST_STATE_NULL); gst_object_unref(gstctx.pipeline); @@ -844,5 +843,10 @@ wth_receiver_weston_main(struct window *window, const char *app_id, int port) destroy_display(gstctx.display); free(gargv); - return 0; + fprintf(stdout, "Exiting, closed down gstreamer pipeline\n"); + /* note, we do a exit here because wth_receiver_weston_main() isn't + * really C's main() and we fork() before calling this. Doing a return + * will not correctly signal the parent that the child process exited + */ + exit(EXIT_SUCCESS); } 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); diff --git a/src/wth-receiver-seat.c b/src/wth-receiver-seat.c index f4b4886..f137e01 100644 --- a/src/wth-receiver-seat.c +++ b/src/wth-receiver-seat.c @@ -35,9 +35,9 @@ waltham_touch_down(struct window *window, uint32_t serial, uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) { - struct surface *surface = window->receiver_surf; struct seat *seat = window->receiver_seat; struct touch *touch = seat->touch; + struct surface *surface = window->receiver_surf; if (!touch) { fprintf(stderr, "We do not have touch device!\n"); @@ -45,7 +45,6 @@ waltham_touch_down(struct window *window, uint32_t serial, } if (touch->obj) { - fprintf(stdout, "waltham_touch_down() sending touch_down\n"); wthp_touch_send_down(touch->obj, serial, time, surface->obj, id, x_w, y_w); } return; @@ -64,7 +63,6 @@ waltham_touch_up(struct window *window, uint32_t serial, } if (touch->obj) { - fprintf(stdout, "waltham_touch_motion() sending touch_up\n"); wthp_touch_send_up(touch->obj, serial, time, id); } return; @@ -83,7 +81,6 @@ waltham_touch_motion(struct window *window, uint32_t time, } if (touch->obj) { - fprintf(stdout, "waltham_touch_motion() sending touch_motion\n"); wthp_touch_send_motion(touch->obj, time, id, x_w, y_w); } } @@ -100,7 +97,6 @@ waltham_touch_frame(struct window *window) } if (touch->obj) { - fprintf(stdout, "waltham_touch_frame() sending frame\n"); wthp_touch_send_frame(touch->obj); } } @@ -353,9 +349,6 @@ client_bind_seat(struct client *c, struct wthp_seat *obj) seat->client = c; wl_list_insert(&c->seat_list, &seat->link); - fprintf(stdout, "wthp_seat object=%p and seat=%p\n",obj,seat); wthp_seat_set_interface(obj, &seat_implementation, seat); - - fprintf(stdout, "client %p bound wthp_seat\n", c); seat_send_updated_caps(seat); } |