17d62b00eSchristos /* Async events for the GDB event loop. 2*6881a400Schristos Copyright (C) 1999-2023 Free Software Foundation, Inc. 37d62b00eSchristos 47d62b00eSchristos This file is part of GDB. 57d62b00eSchristos 67d62b00eSchristos This program is free software; you can redistribute it and/or modify 77d62b00eSchristos it under the terms of the GNU General Public License as published by 87d62b00eSchristos the Free Software Foundation; either version 3 of the License, or 97d62b00eSchristos (at your option) any later version. 107d62b00eSchristos 117d62b00eSchristos This program is distributed in the hope that it will be useful, 127d62b00eSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 137d62b00eSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147d62b00eSchristos GNU General Public License for more details. 157d62b00eSchristos 167d62b00eSchristos You should have received a copy of the GNU General Public License 177d62b00eSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 187d62b00eSchristos 197d62b00eSchristos #include "defs.h" 207d62b00eSchristos #include "async-event.h" 217d62b00eSchristos 227d62b00eSchristos #include "ser-event.h" 237d62b00eSchristos #include "top.h" 247d62b00eSchristos 257d62b00eSchristos /* PROC is a function to be invoked when the READY flag is set. This 267d62b00eSchristos happens when there has been a signal and the corresponding signal 277d62b00eSchristos handler has 'triggered' this async_signal_handler for execution. 287d62b00eSchristos The actual work to be done in response to a signal will be carried 297d62b00eSchristos out by PROC at a later time, within process_event. This provides a 307d62b00eSchristos deferred execution of signal handlers. 317d62b00eSchristos 327d62b00eSchristos Async_init_signals takes care of setting up such an 337d62b00eSchristos async_signal_handler for each interesting signal. */ 347d62b00eSchristos 357d62b00eSchristos struct async_signal_handler 367d62b00eSchristos { 377d62b00eSchristos /* If ready, call this handler from the main event loop, using 387d62b00eSchristos invoke_async_handler. */ 397d62b00eSchristos int ready; 407d62b00eSchristos 417d62b00eSchristos /* Pointer to next handler. */ 427d62b00eSchristos struct async_signal_handler *next_handler; 437d62b00eSchristos 447d62b00eSchristos /* Function to call to do the work. */ 457d62b00eSchristos sig_handler_func *proc; 467d62b00eSchristos 477d62b00eSchristos /* Argument to PROC. */ 487d62b00eSchristos gdb_client_data client_data; 49*6881a400Schristos 50*6881a400Schristos /* User-friendly name of this handler. */ 51*6881a400Schristos const char *name; 527d62b00eSchristos }; 537d62b00eSchristos 547d62b00eSchristos /* PROC is a function to be invoked when the READY flag is set. This 557d62b00eSchristos happens when the event has been marked with 567d62b00eSchristos MARK_ASYNC_EVENT_HANDLER. The actual work to be done in response 577d62b00eSchristos to an event will be carried out by PROC at a later time, within 587d62b00eSchristos process_event. This provides a deferred execution of event 597d62b00eSchristos handlers. */ 607d62b00eSchristos struct async_event_handler 617d62b00eSchristos { 627d62b00eSchristos /* If ready, call this handler from the main event loop, using 637d62b00eSchristos invoke_event_handler. */ 647d62b00eSchristos int ready; 657d62b00eSchristos 667d62b00eSchristos /* Pointer to next handler. */ 677d62b00eSchristos struct async_event_handler *next_handler; 687d62b00eSchristos 697d62b00eSchristos /* Function to call to do the work. */ 707d62b00eSchristos async_event_handler_func *proc; 717d62b00eSchristos 727d62b00eSchristos /* Argument to PROC. */ 737d62b00eSchristos gdb_client_data client_data; 74*6881a400Schristos 75*6881a400Schristos /* User-friendly name of this handler. */ 76*6881a400Schristos const char *name; 777d62b00eSchristos }; 787d62b00eSchristos 797d62b00eSchristos /* All the async_signal_handlers gdb is interested in are kept onto 807d62b00eSchristos this list. */ 817d62b00eSchristos static struct 827d62b00eSchristos { 837d62b00eSchristos /* Pointer to first in handler list. */ 847d62b00eSchristos async_signal_handler *first_handler; 857d62b00eSchristos 867d62b00eSchristos /* Pointer to last in handler list. */ 877d62b00eSchristos async_signal_handler *last_handler; 887d62b00eSchristos } 897d62b00eSchristos sighandler_list; 907d62b00eSchristos 917d62b00eSchristos /* All the async_event_handlers gdb is interested in are kept onto 927d62b00eSchristos this list. */ 937d62b00eSchristos static struct 947d62b00eSchristos { 957d62b00eSchristos /* Pointer to first in handler list. */ 967d62b00eSchristos async_event_handler *first_handler; 977d62b00eSchristos 987d62b00eSchristos /* Pointer to last in handler list. */ 997d62b00eSchristos async_event_handler *last_handler; 1007d62b00eSchristos } 1017d62b00eSchristos async_event_handler_list; 1027d62b00eSchristos 1037d62b00eSchristos 1047d62b00eSchristos /* This event is signalled whenever an asynchronous handler needs to 1057d62b00eSchristos defer an action to the event loop. */ 1067d62b00eSchristos static struct serial_event *async_signal_handlers_serial_event; 1077d62b00eSchristos 1087d62b00eSchristos /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT. */ 1097d62b00eSchristos 1107d62b00eSchristos static void 1117d62b00eSchristos async_signals_handler (int error, gdb_client_data client_data) 1127d62b00eSchristos { 1137d62b00eSchristos /* Do nothing. Handlers are run by invoke_async_signal_handlers 1147d62b00eSchristos from instead. */ 1157d62b00eSchristos } 1167d62b00eSchristos 1177d62b00eSchristos void 1187d62b00eSchristos initialize_async_signal_handlers (void) 1197d62b00eSchristos { 1207d62b00eSchristos async_signal_handlers_serial_event = make_serial_event (); 1217d62b00eSchristos 1227d62b00eSchristos add_file_handler (serial_event_fd (async_signal_handlers_serial_event), 123*6881a400Schristos async_signals_handler, NULL, "async-signals"); 1247d62b00eSchristos } 1257d62b00eSchristos 1267d62b00eSchristos 1277d62b00eSchristos 1287d62b00eSchristos /* Create an asynchronous handler, allocating memory for it. 1297d62b00eSchristos Return a pointer to the newly created handler. 1307d62b00eSchristos This pointer will be used to invoke the handler by 1317d62b00eSchristos invoke_async_signal_handler. 1327d62b00eSchristos PROC is the function to call with CLIENT_DATA argument 1337d62b00eSchristos whenever the handler is invoked. */ 1347d62b00eSchristos async_signal_handler * 1357d62b00eSchristos create_async_signal_handler (sig_handler_func * proc, 136*6881a400Schristos gdb_client_data client_data, 137*6881a400Schristos const char *name) 1387d62b00eSchristos { 1397d62b00eSchristos async_signal_handler *async_handler_ptr; 1407d62b00eSchristos 1417d62b00eSchristos async_handler_ptr = XNEW (async_signal_handler); 1427d62b00eSchristos async_handler_ptr->ready = 0; 1437d62b00eSchristos async_handler_ptr->next_handler = NULL; 1447d62b00eSchristos async_handler_ptr->proc = proc; 1457d62b00eSchristos async_handler_ptr->client_data = client_data; 146*6881a400Schristos async_handler_ptr->name = name; 1477d62b00eSchristos if (sighandler_list.first_handler == NULL) 1487d62b00eSchristos sighandler_list.first_handler = async_handler_ptr; 1497d62b00eSchristos else 1507d62b00eSchristos sighandler_list.last_handler->next_handler = async_handler_ptr; 1517d62b00eSchristos sighandler_list.last_handler = async_handler_ptr; 1527d62b00eSchristos return async_handler_ptr; 1537d62b00eSchristos } 1547d62b00eSchristos 1557d62b00eSchristos /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information 1567d62b00eSchristos will be used when the handlers are invoked, after we have waited 1577d62b00eSchristos for some event. The caller of this function is the interrupt 1587d62b00eSchristos handler associated with a signal. */ 1597d62b00eSchristos void 1607d62b00eSchristos mark_async_signal_handler (async_signal_handler *async_handler_ptr) 1617d62b00eSchristos { 162*6881a400Schristos if (debug_event_loop != debug_event_loop_kind::OFF) 163*6881a400Schristos { 164*6881a400Schristos /* This is called by signal handlers, so we print it "by hand" using 165*6881a400Schristos the async-signal-safe methods. */ 166*6881a400Schristos const char head[] = ("[event-loop] mark_async_signal_handler: marking" 167*6881a400Schristos "async signal handler `"); 168*6881a400Schristos gdb_stdlog->write_async_safe (head, strlen (head)); 169*6881a400Schristos 170*6881a400Schristos gdb_stdlog->write_async_safe (async_handler_ptr->name, 171*6881a400Schristos strlen (async_handler_ptr->name)); 172*6881a400Schristos 173*6881a400Schristos const char tail[] = "`\n"; 174*6881a400Schristos gdb_stdlog->write_async_safe (tail, strlen (tail)); 175*6881a400Schristos } 176*6881a400Schristos 1777d62b00eSchristos async_handler_ptr->ready = 1; 1787d62b00eSchristos serial_event_set (async_signal_handlers_serial_event); 1797d62b00eSchristos } 1807d62b00eSchristos 1817d62b00eSchristos /* See event-loop.h. */ 1827d62b00eSchristos 1837d62b00eSchristos void 1847d62b00eSchristos clear_async_signal_handler (async_signal_handler *async_handler_ptr) 1857d62b00eSchristos { 186*6881a400Schristos event_loop_debug_printf ("clearing async signal handler `%s`", 187*6881a400Schristos async_handler_ptr->name); 1887d62b00eSchristos async_handler_ptr->ready = 0; 1897d62b00eSchristos } 1907d62b00eSchristos 1917d62b00eSchristos /* See event-loop.h. */ 1927d62b00eSchristos 1937d62b00eSchristos int 1947d62b00eSchristos async_signal_handler_is_marked (async_signal_handler *async_handler_ptr) 1957d62b00eSchristos { 1967d62b00eSchristos return async_handler_ptr->ready; 1977d62b00eSchristos } 1987d62b00eSchristos 1997d62b00eSchristos /* Call all the handlers that are ready. Returns true if any was 2007d62b00eSchristos indeed ready. */ 2017d62b00eSchristos 2027d62b00eSchristos int 2037d62b00eSchristos invoke_async_signal_handlers (void) 2047d62b00eSchristos { 2057d62b00eSchristos async_signal_handler *async_handler_ptr; 2067d62b00eSchristos int any_ready = 0; 2077d62b00eSchristos 2087d62b00eSchristos /* We're going to handle all pending signals, so no need to wake up 2097d62b00eSchristos the event loop again the next time around. Note this must be 2107d62b00eSchristos cleared _before_ calling the callbacks, to avoid races. */ 2117d62b00eSchristos serial_event_clear (async_signal_handlers_serial_event); 2127d62b00eSchristos 2137d62b00eSchristos /* Invoke all ready handlers. */ 2147d62b00eSchristos 2157d62b00eSchristos while (1) 2167d62b00eSchristos { 2177d62b00eSchristos for (async_handler_ptr = sighandler_list.first_handler; 2187d62b00eSchristos async_handler_ptr != NULL; 2197d62b00eSchristos async_handler_ptr = async_handler_ptr->next_handler) 2207d62b00eSchristos { 2217d62b00eSchristos if (async_handler_ptr->ready) 2227d62b00eSchristos break; 2237d62b00eSchristos } 2247d62b00eSchristos if (async_handler_ptr == NULL) 2257d62b00eSchristos break; 2267d62b00eSchristos any_ready = 1; 2277d62b00eSchristos async_handler_ptr->ready = 0; 2287d62b00eSchristos /* Async signal handlers have no connection to whichever was the 2297d62b00eSchristos current UI, and thus always run on the main one. */ 2307d62b00eSchristos current_ui = main_ui; 231*6881a400Schristos event_loop_debug_printf ("invoking async signal handler `%s`", 232*6881a400Schristos async_handler_ptr->name); 2337d62b00eSchristos (*async_handler_ptr->proc) (async_handler_ptr->client_data); 2347d62b00eSchristos } 2357d62b00eSchristos 2367d62b00eSchristos return any_ready; 2377d62b00eSchristos } 2387d62b00eSchristos 2397d62b00eSchristos /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 2407d62b00eSchristos Free the space allocated for it. */ 2417d62b00eSchristos void 2427d62b00eSchristos delete_async_signal_handler (async_signal_handler ** async_handler_ptr) 2437d62b00eSchristos { 2447d62b00eSchristos async_signal_handler *prev_ptr; 2457d62b00eSchristos 2467d62b00eSchristos if (sighandler_list.first_handler == (*async_handler_ptr)) 2477d62b00eSchristos { 2487d62b00eSchristos sighandler_list.first_handler = (*async_handler_ptr)->next_handler; 2497d62b00eSchristos if (sighandler_list.first_handler == NULL) 2507d62b00eSchristos sighandler_list.last_handler = NULL; 2517d62b00eSchristos } 2527d62b00eSchristos else 2537d62b00eSchristos { 2547d62b00eSchristos prev_ptr = sighandler_list.first_handler; 2557d62b00eSchristos while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr)) 2567d62b00eSchristos prev_ptr = prev_ptr->next_handler; 2577d62b00eSchristos gdb_assert (prev_ptr); 2587d62b00eSchristos prev_ptr->next_handler = (*async_handler_ptr)->next_handler; 2597d62b00eSchristos if (sighandler_list.last_handler == (*async_handler_ptr)) 2607d62b00eSchristos sighandler_list.last_handler = prev_ptr; 2617d62b00eSchristos } 2627d62b00eSchristos xfree ((*async_handler_ptr)); 2637d62b00eSchristos (*async_handler_ptr) = NULL; 2647d62b00eSchristos } 2657d62b00eSchristos 266*6881a400Schristos /* See async-event.h. */ 267*6881a400Schristos 2687d62b00eSchristos async_event_handler * 2697d62b00eSchristos create_async_event_handler (async_event_handler_func *proc, 270*6881a400Schristos gdb_client_data client_data, 271*6881a400Schristos const char *name) 2727d62b00eSchristos { 2737d62b00eSchristos async_event_handler *h; 2747d62b00eSchristos 2757d62b00eSchristos h = XNEW (struct async_event_handler); 2767d62b00eSchristos h->ready = 0; 2777d62b00eSchristos h->next_handler = NULL; 2787d62b00eSchristos h->proc = proc; 2797d62b00eSchristos h->client_data = client_data; 280*6881a400Schristos h->name = name; 2817d62b00eSchristos if (async_event_handler_list.first_handler == NULL) 2827d62b00eSchristos async_event_handler_list.first_handler = h; 2837d62b00eSchristos else 2847d62b00eSchristos async_event_handler_list.last_handler->next_handler = h; 2857d62b00eSchristos async_event_handler_list.last_handler = h; 2867d62b00eSchristos return h; 2877d62b00eSchristos } 2887d62b00eSchristos 2897d62b00eSchristos /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information 2907d62b00eSchristos will be used by gdb_do_one_event. The caller will be whoever 2917d62b00eSchristos created the event source, and wants to signal that the event is 2927d62b00eSchristos ready to be handled. */ 2937d62b00eSchristos void 2947d62b00eSchristos mark_async_event_handler (async_event_handler *async_handler_ptr) 2957d62b00eSchristos { 296*6881a400Schristos event_loop_debug_printf ("marking async event handler `%s` " 297*6881a400Schristos "(previous state was %d)", 298*6881a400Schristos async_handler_ptr->name, 299*6881a400Schristos async_handler_ptr->ready); 3007d62b00eSchristos async_handler_ptr->ready = 1; 3017d62b00eSchristos } 3027d62b00eSchristos 3037d62b00eSchristos /* See event-loop.h. */ 3047d62b00eSchristos 3057d62b00eSchristos void 3067d62b00eSchristos clear_async_event_handler (async_event_handler *async_handler_ptr) 3077d62b00eSchristos { 308*6881a400Schristos event_loop_debug_printf ("clearing async event handler `%s`", 309*6881a400Schristos async_handler_ptr->name); 3107d62b00eSchristos async_handler_ptr->ready = 0; 3117d62b00eSchristos } 3127d62b00eSchristos 313*6881a400Schristos /* See event-loop.h. */ 314*6881a400Schristos 315*6881a400Schristos bool 316*6881a400Schristos async_event_handler_marked (async_event_handler *handler) 317*6881a400Schristos { 318*6881a400Schristos return handler->ready; 319*6881a400Schristos } 320*6881a400Schristos 3217d62b00eSchristos /* Check if asynchronous event handlers are ready, and call the 3227d62b00eSchristos handler function for one that is. */ 3237d62b00eSchristos 3247d62b00eSchristos int 3257d62b00eSchristos check_async_event_handlers () 3267d62b00eSchristos { 3277d62b00eSchristos async_event_handler *async_handler_ptr; 3287d62b00eSchristos 3297d62b00eSchristos for (async_handler_ptr = async_event_handler_list.first_handler; 3307d62b00eSchristos async_handler_ptr != NULL; 3317d62b00eSchristos async_handler_ptr = async_handler_ptr->next_handler) 3327d62b00eSchristos { 3337d62b00eSchristos if (async_handler_ptr->ready) 3347d62b00eSchristos { 335*6881a400Schristos event_loop_debug_printf ("invoking async event handler `%s`", 336*6881a400Schristos async_handler_ptr->name); 3377d62b00eSchristos (*async_handler_ptr->proc) (async_handler_ptr->client_data); 3387d62b00eSchristos return 1; 3397d62b00eSchristos } 3407d62b00eSchristos } 3417d62b00eSchristos 3427d62b00eSchristos return 0; 3437d62b00eSchristos } 3447d62b00eSchristos 3457d62b00eSchristos /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 3467d62b00eSchristos Free the space allocated for it. */ 3477d62b00eSchristos void 3487d62b00eSchristos delete_async_event_handler (async_event_handler **async_handler_ptr) 3497d62b00eSchristos { 3507d62b00eSchristos async_event_handler *prev_ptr; 3517d62b00eSchristos 3527d62b00eSchristos if (async_event_handler_list.first_handler == *async_handler_ptr) 3537d62b00eSchristos { 3547d62b00eSchristos async_event_handler_list.first_handler 3557d62b00eSchristos = (*async_handler_ptr)->next_handler; 3567d62b00eSchristos if (async_event_handler_list.first_handler == NULL) 3577d62b00eSchristos async_event_handler_list.last_handler = NULL; 3587d62b00eSchristos } 3597d62b00eSchristos else 3607d62b00eSchristos { 3617d62b00eSchristos prev_ptr = async_event_handler_list.first_handler; 3627d62b00eSchristos while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr) 3637d62b00eSchristos prev_ptr = prev_ptr->next_handler; 3647d62b00eSchristos gdb_assert (prev_ptr); 3657d62b00eSchristos prev_ptr->next_handler = (*async_handler_ptr)->next_handler; 3667d62b00eSchristos if (async_event_handler_list.last_handler == (*async_handler_ptr)) 3677d62b00eSchristos async_event_handler_list.last_handler = prev_ptr; 3687d62b00eSchristos } 3697d62b00eSchristos xfree (*async_handler_ptr); 3707d62b00eSchristos *async_handler_ptr = NULL; 3717d62b00eSchristos } 372