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