From 17fa95f7791dd24a7036259abaa6aa7c9f13fdb7 Mon Sep 17 00:00:00 2001 From: Denis Date: Wed, 13 Dec 2023 15:16:40 +0100 Subject: [PATCH] all-in-one should now be able to exit correctly --- allynone.c | 60 +++++++++++++++++++++------- dev_in.c | 5 +++ dev_in.h | 4 ++ dev_out.c | 108 ++++++++++++++++++++++++++++++-------------------- dev_out.h | 4 ++ rogue_enemy.h | 2 + stray_ally.c | 3 ++ 7 files changed, 129 insertions(+), 57 deletions(-) diff --git a/allynone.c b/allynone.c index 572191b..683ca37 100644 --- a/allynone.c +++ b/allynone.c @@ -39,13 +39,6 @@ int main(int argc, char ** argv) { init_config(&settings); fill_config(&settings, configuration_file); -/* - const int logic_creation_res = logic_create(&global_logic); - if (logic_creation_res < 0) { - fprintf(stderr, "Unable to create logic: %d", logic_creation_res); - return EXIT_FAILURE; - } -*/ input_dev_composite_t* in_devs = NULL; int dmi_name_fd = open("/sys/class/dmi/id/board_name", O_RDONLY | O_NONBLOCK); @@ -75,6 +68,24 @@ int main(int argc, char ** argv) { int in_message_pipes[2]; pipe(in_message_pipes); + // Create a signal set containing only SIGTERM + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGTERM); + + // Block SIGTERM for the current thread + if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { + perror("sigprocmask"); + exit(EXIT_FAILURE); + } + + // Create a signalfd for the specified signals + int sfd = signalfd(-1, &mask, 0); + if (sfd == -1) { + perror("signalfd"); + exit(EXIT_FAILURE); + } + // populate the input device thread data dev_in_thread_data.timeout_ms = 400; dev_in_thread_data.communication.type = ipc_unix_pipe; @@ -106,14 +117,35 @@ int main(int argc, char ** argv) { goto main_err; } -/* - // TODO: once the application is able to exit de-comment this - __sighandler_t sigint_hndl = signal(SIGINT, sig_handler); - if (sigint_hndl == SIG_ERR) { - fprintf(stderr, "Error registering SIGINT handler\n"); - return EXIT_FAILURE; + struct pollfd sigpoll = { + .fd = sfd, + .events = POLL_IN, + }; + + for (;;) { + sigpoll.revents = 0; + + poll(&sigpoll, 1, 400); + + if (sigpoll.revents & POLL_IN) { + // Read signals from the signalfd + struct signalfd_siginfo si; + ssize_t s = read(sfd, &si, sizeof(struct signalfd_siginfo)); + + if (s != sizeof(struct signalfd_siginfo)) { + perror("Error reading signalfd\n"); + exit(EXIT_FAILURE); + } + + // Check the signal received + if (si.ssi_signo == SIGTERM) { + printf("Received SIGTERM -- propagating signal\n"); + dev_in_thread_data.flags |= DEV_IN_FLAG_EXIT; + dev_out_thread_data.flags |= DEV_OUT_FLAG_EXIT; + break; + } + } } -*/ main_err: if (dev_in_thread_creation == 0) { diff --git a/dev_in.c b/dev_in.c index ebf4497..33afe3a 100644 --- a/dev_in.c +++ b/dev_in.c @@ -340,6 +340,11 @@ void* dev_in_thread_func(void *ptr) { } for (;;) { + if (dev_in_data->flags & DEV_IN_FLAG_EXIT) { + printf("Termination signal received -- exiting dev_in\n"); + break; + } + FD_ZERO(&read_fds); if (dev_in_data->communication.type == ipc_unix_pipe) { diff --git a/dev_in.h b/dev_in.h index 18bc8e2..d66c0cf 100644 --- a/dev_in.h +++ b/dev_in.h @@ -6,6 +6,8 @@ #define MAX_IN_MESSAGES 8 +#define DEV_IN_FLAG_EXIT 0x00000001U + typedef struct dev_in_data { size_t max_messages_in_flight; @@ -17,6 +19,8 @@ typedef struct dev_in_data { ipc_t communication; + volatile uint32_t flags; + } dev_in_data_t; void *dev_in_thread_func(void *ptr); diff --git a/dev_out.c b/dev_out.c index 3a1b730..0ccd5a7 100644 --- a/dev_out.c +++ b/dev_out.c @@ -161,12 +161,12 @@ int64_t get_timediff_usec(const struct timeval *const past, const struct timeval } void *dev_out_thread_func(void *ptr) { - dev_out_data_t *const dev_out = (dev_out_data_t*)ptr; + dev_out_data_t *const dev_out_data = (dev_out_data_t*)ptr; // Initialize device - devices_status_init(&dev_out->dev_stats); + devices_status_init(&dev_out_data->dev_stats); - dev_out_gamepad_device_t current_gamepad = dev_out->gamepad; + dev_out_gamepad_device_t current_gamepad = dev_out_data->gamepad; union { virt_dualshock_t ds4; @@ -206,33 +206,38 @@ void *dev_out_thread_func(void *ptr) { fd_set read_fds; for (;;) { + if (dev_out_data->flags & DEV_OUT_FLAG_EXIT) { + printf("Termination signal received -- exiting dev_out\n"); + break; + } + gettimeofday(&now, NULL); int64_t gamepad_time_diff_usecs = get_timediff_usec(&gamepad_last_hid_report_sent, &now); if (gamepad_time_diff_usecs >= 1250) { gamepad_last_hid_report_sent = now; if (current_gamepad == GAMEPAD_DUALSENSE) { - virt_dualsense_compose(&controller_data.ds5, &dev_out->dev_stats.gamepad, tmp_buf); + virt_dualsense_compose(&controller_data.ds5, &dev_out_data->dev_stats.gamepad, tmp_buf); virt_dualsense_send(&controller_data.ds5, tmp_buf); } else if (current_gamepad == GAMEPAD_DUALSHOCK) { - virt_dualshock_compose(&controller_data.ds4, &dev_out->dev_stats.gamepad, tmp_buf); + virt_dualshock_compose(&controller_data.ds4, &dev_out_data->dev_stats.gamepad, tmp_buf); virt_dualshock_send(&controller_data.ds4, tmp_buf); } } else { FD_ZERO(&read_fds); - if (dev_out->communication.type == ipc_unix_pipe) { - FD_SET(dev_out->communication.endpoint.pipe.in_message_pipe_fd, &read_fds); - } else if (dev_out->communication.type == ipc_server_sockets) { - if (pthread_mutex_lock(&dev_out->communication.endpoint.ssocket.mutex) == 0) { + if (dev_out_data->communication.type == ipc_unix_pipe) { + FD_SET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds); + } else if (dev_out_data->communication.type == ipc_server_sockets) { + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - const int fd = dev_out->communication.endpoint.ssocket.clients[i]; + const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; if (fd > 0) { FD_SET(fd, &read_fds); } } - pthread_mutex_unlock(&dev_out->communication.endpoint.ssocket.mutex); + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); } } @@ -247,7 +252,7 @@ void *dev_out_thread_func(void *ptr) { }; int ready_fds = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); - gamepad_status_qam_quirk_ext_time(&dev_out->dev_stats.gamepad, &now); + gamepad_status_qam_quirk_ext_time(&dev_out_data->dev_stats.gamepad, &now); if (ready_fds == -1) { const int err = errno; @@ -260,28 +265,28 @@ void *dev_out_thread_func(void *ptr) { if (FD_ISSET(current_gamepad_fd, &read_fds)) { - const uint64_t prev_leds_events_count = dev_out->dev_stats.gamepad.leds_events_count; - const uint64_t prev_motors_events_count = dev_out->dev_stats.gamepad.rumble_events_count; + const uint64_t prev_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; + const uint64_t prev_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; out_message_t out_msgs[4]; size_t out_msgs_count = 0; if (current_gamepad == GAMEPAD_DUALSENSE) { - virt_dualsense_event(&controller_data.ds5, &dev_out->dev_stats.gamepad); + virt_dualsense_event(&controller_data.ds5, &dev_out_data->dev_stats.gamepad); } else if (current_gamepad == GAMEPAD_DUALSHOCK) { - virt_dualshock_event(&controller_data.ds4, &dev_out->dev_stats.gamepad); + virt_dualshock_event(&controller_data.ds4, &dev_out_data->dev_stats.gamepad); } - const uint64_t current_leds_events_count = dev_out->dev_stats.gamepad.leds_events_count; - const uint64_t current_motors_events_count = dev_out->dev_stats.gamepad.rumble_events_count; + const uint64_t current_leds_events_count = dev_out_data->dev_stats.gamepad.leds_events_count; + const uint64_t current_motors_events_count = dev_out_data->dev_stats.gamepad.rumble_events_count; if (current_leds_events_count != prev_leds_events_count) { const out_message_t msg = { .type = OUT_MSG_TYPE_LEDS, .data = { .leds = { - .r = dev_out->dev_stats.gamepad.leds_colors[0], - .g = dev_out->dev_stats.gamepad.leds_colors[1], - .b = dev_out->dev_stats.gamepad.leds_colors[2], + .r = dev_out_data->dev_stats.gamepad.leds_colors[0], + .g = dev_out_data->dev_stats.gamepad.leds_colors[1], + .b = dev_out_data->dev_stats.gamepad.leds_colors[2], } } }; @@ -294,8 +299,8 @@ void *dev_out_thread_func(void *ptr) { .type = OUT_MSG_TYPE_RUMBLE, .data = { .rumble = { - .motors_left = dev_out->dev_stats.gamepad.motors_intensity[0], - .motors_right = dev_out->dev_stats.gamepad.motors_intensity[1], + .motors_left = dev_out_data->dev_stats.gamepad.motors_intensity[0], + .motors_right = dev_out_data->dev_stats.gamepad.motors_intensity[1], } } }; @@ -307,58 +312,58 @@ void *dev_out_thread_func(void *ptr) { int fd = -1; const size_t bytes_to_send = sizeof(out_message_t) * out_msgs_count; - if (dev_out->communication.type == ipc_unix_pipe) { - const int write_res = write(dev_out->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs, bytes_to_send); + if (dev_out_data->communication.type == ipc_unix_pipe) { + const int write_res = write(dev_out_data->communication.endpoint.pipe.out_message_pipe_fd, (void*)&out_msgs, bytes_to_send); if (write_res != bytes_to_send) { fprintf(stderr, "Error in writing out_message to out_message_pipe: %d\n", write_res); } - } else if (dev_out->communication.type == ipc_server_sockets) { - if (pthread_mutex_lock(&dev_out->communication.endpoint.ssocket.mutex) == 0) { + } else if (dev_out_data->communication.type == ipc_server_sockets) { + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - if (dev_out->communication.endpoint.ssocket.clients[i] > 0) { - const int write_res = write(dev_out->communication.endpoint.ssocket.clients[i], (void*)&out_msgs, bytes_to_send); + if (dev_out_data->communication.endpoint.ssocket.clients[i] > 0) { + const int write_res = write(dev_out_data->communication.endpoint.ssocket.clients[i], (void*)&out_msgs, bytes_to_send); if (write_res != bytes_to_send) { fprintf(stderr, "Error in writing out_message to socket number %d: %d\n", i, write_res); - close(dev_out->communication.endpoint.ssocket.clients[i]); - dev_out->communication.endpoint.ssocket.clients[i] = -1; + close(dev_out_data->communication.endpoint.ssocket.clients[i]); + dev_out_data->communication.endpoint.ssocket.clients[i] = -1; } } } - pthread_mutex_unlock(&dev_out->communication.endpoint.ssocket.mutex); + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); } } } // read and handle incoming data: this data is packed into in_message_t - if (dev_out->communication.type == ipc_unix_pipe) { - if (FD_ISSET(dev_out->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) { + if (dev_out_data->communication.type == ipc_unix_pipe) { + if (FD_ISSET(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, &read_fds)) { in_message_t incoming_message; - const size_t in_message_pipe_read_res = read(dev_out->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t)); + const size_t in_message_pipe_read_res = read(dev_out_data->communication.endpoint.pipe.in_message_pipe_fd, (void*)&incoming_message, sizeof(in_message_t)); if (in_message_pipe_read_res == sizeof(in_message_t)) { - handle_incoming_message(&incoming_message, &dev_out->dev_stats); + handle_incoming_message(&incoming_message, &dev_out_data->dev_stats); } else { fprintf(stderr, "Error reading from in_message_pipe_fd: got %zu bytes, expected %zu butes\n", in_message_pipe_read_res, sizeof(in_message_t)); } } - } else if (dev_out->communication.type == ipc_server_sockets) { - if (pthread_mutex_lock(&dev_out->communication.endpoint.ssocket.mutex) == 0) { + } else if (dev_out_data->communication.type == ipc_server_sockets) { + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { - const int fd = dev_out->communication.endpoint.ssocket.clients[i]; + const int fd = dev_out_data->communication.endpoint.ssocket.clients[i]; if ((fd > 0) && (FD_ISSET(fd, &read_fds))) { in_message_t incoming_message; const size_t in_message_pipe_read_res = read(fd, (void*)&incoming_message, sizeof(in_message_t)); if (in_message_pipe_read_res == sizeof(in_message_t)) { - handle_incoming_message(&incoming_message, &dev_out->dev_stats); + handle_incoming_message(&incoming_message, &dev_out_data->dev_stats); } else { fprintf(stderr, "Error reading from socket number %d: got %zu bytes, expected %zu butes\n", i, in_message_pipe_read_res, sizeof(in_message_t)); - close(dev_out->communication.endpoint.ssocket.clients[i]); - dev_out->communication.endpoint.ssocket.clients[i] = -1; + close(dev_out_data->communication.endpoint.ssocket.clients[i]); + dev_out_data->communication.endpoint.ssocket.clients[i] = -1; } } } - pthread_mutex_unlock(&dev_out->communication.endpoint.ssocket.mutex); + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); } } @@ -366,5 +371,22 @@ void *dev_out_thread_func(void *ptr) { } } + // close the output device + if (current_gamepad == GAMEPAD_DUALSENSE) { + virt_dualsense_close(&controller_data.ds5); + } else if (current_gamepad == GAMEPAD_DUALSHOCK) { + virt_dualshock_close(&controller_data.ds4); + } + + // close every thread + if (pthread_mutex_lock(&dev_out_data->communication.endpoint.ssocket.mutex) == 0) { + for (int i = 0; i < MAX_CONNECTED_CLIENTS; ++i) { + close(dev_out_data->communication.endpoint.ssocket.clients[i]); + dev_out_data->communication.endpoint.ssocket.clients[i] = -1; + } + + pthread_mutex_unlock(&dev_out_data->communication.endpoint.ssocket.mutex); + } + return NULL; } diff --git a/dev_out.h b/dev_out.h index 9da81c3..a0c249c 100644 --- a/dev_out.h +++ b/dev_out.h @@ -4,6 +4,8 @@ #include "message.h" #include "devices_status.h" +#define DEV_OUT_FLAG_EXIT 0x00000001U + typedef enum dev_out_gamepad_device { GAMEPAD_DUALSENSE, GAMEPAD_DUALSHOCK, @@ -18,6 +20,8 @@ typedef struct dev_out_data { devices_status_t dev_stats; + volatile uint32_t flags; + } dev_out_data_t; void *dev_out_thread_func(void *ptr); diff --git a/rogue_enemy.h b/rogue_enemy.h index 9a8b918..1e7cfac 100644 --- a/rogue_enemy.h +++ b/rogue_enemy.h @@ -1,5 +1,7 @@ #pragma once +#define _GNU_SOURCE + #include #include #include diff --git a/stray_ally.c b/stray_ally.c index 5322cbb..2439677 100644 --- a/stray_ally.c +++ b/stray_ally.c @@ -68,6 +68,9 @@ int main(int argc, char ** argv) { int sd=-1; struct sockaddr_un serveraddr; do { + poll_fds[0].revents = 0; + poll_fds[1].revents = 0; + sd = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (sd < 0) {