1 /* Async events for the GDB event loop.
2    Copyright (C) 1999-2024 Free Software Foundation, Inc.
3 
4    This file is part of GDB.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include "async-event.h"
20 
21 #include "ser-event.h"
22 #include "top.h"
23 #include "ui.h"
24 
25 /* PROC is a function to be invoked when the READY flag is set.  This
26    happens when there has been a signal and the corresponding signal
27    handler has 'triggered' this async_signal_handler for execution.
28    The actual work to be done in response to a signal will be carried
29    out by PROC at a later time, within process_event.  This provides a
30    deferred execution of signal handlers.
31 
32    Async_init_signals takes care of setting up such an
33    async_signal_handler for each interesting signal.  */
34 
35 struct async_signal_handler
36 {
37   /* If ready, call this handler  from the main event loop, using
38      invoke_async_handler.  */
39   int ready;
40 
41   /* Pointer to next handler.  */
42   struct async_signal_handler *next_handler;
43 
44   /* Function to call to do the work.  */
45   sig_handler_func *proc;
46 
47   /* Argument to PROC.  */
48   gdb_client_data client_data;
49 
50   /* User-friendly name of this handler.  */
51   const char *name;
52 };
53 
54 /* PROC is a function to be invoked when the READY flag is set.  This
55    happens when the event has been marked with
56    MARK_ASYNC_EVENT_HANDLER.  The actual work to be done in response
57    to an event will be carried out by PROC at a later time, within
58    process_event.  This provides a deferred execution of event
59    handlers.  */
60 struct async_event_handler
61 {
62   /* If ready, call this handler from the main event loop, using
63      invoke_event_handler.  */
64   int ready;
65 
66   /* Pointer to next handler.  */
67   struct async_event_handler *next_handler;
68 
69   /* Function to call to do the work.  */
70   async_event_handler_func *proc;
71 
72   /* Argument to PROC.  */
73   gdb_client_data client_data;
74 
75   /* User-friendly name of this handler.  */
76   const char *name;
77 };
78 
79 /* All the async_signal_handlers gdb is interested in are kept onto
80    this list.  */
81 static struct
82 {
83   /* Pointer to first in handler list.  */
84   async_signal_handler *first_handler;
85 
86   /* Pointer to last in handler list.  */
87   async_signal_handler *last_handler;
88 }
89 sighandler_list;
90 
91 /* All the async_event_handlers gdb is interested in are kept onto
92    this list.  */
93 static struct
94 {
95   /* Pointer to first in handler list.  */
96   async_event_handler *first_handler;
97 
98   /* Pointer to last in handler list.  */
99   async_event_handler *last_handler;
100 }
101 async_event_handler_list;
102 
103 
104 /* This event is signalled whenever an asynchronous handler needs to
105    defer an action to the event loop.  */
106 static struct serial_event *async_signal_handlers_serial_event;
107 
108 /* Callback registered with ASYNC_SIGNAL_HANDLERS_SERIAL_EVENT.  */
109 
110 static void
async_signals_handler(int error,gdb_client_data client_data)111 async_signals_handler (int error, gdb_client_data client_data)
112 {
113   /* Do nothing.  Handlers are run by invoke_async_signal_handlers
114      from instead.  */
115 }
116 
117 void
initialize_async_signal_handlers(void)118 initialize_async_signal_handlers (void)
119 {
120   async_signal_handlers_serial_event = make_serial_event ();
121 
122   add_file_handler (serial_event_fd (async_signal_handlers_serial_event),
123                         async_signals_handler, NULL, "async-signals");
124 }
125 
126 
127 
128 /* Create an asynchronous handler, allocating memory for it.
129    Return a pointer to the newly created handler.
130    This pointer will be used to invoke the handler by
131    invoke_async_signal_handler.
132    PROC is the function to call with CLIENT_DATA argument
133    whenever the handler is invoked.  */
134 async_signal_handler *
create_async_signal_handler(sig_handler_func * proc,gdb_client_data client_data,const char * name)135 create_async_signal_handler (sig_handler_func * proc,
136                                    gdb_client_data client_data,
137                                    const char *name)
138 {
139   async_signal_handler *async_handler_ptr;
140 
141   async_handler_ptr = XNEW (async_signal_handler);
142   async_handler_ptr->ready = 0;
143   async_handler_ptr->next_handler = NULL;
144   async_handler_ptr->proc = proc;
145   async_handler_ptr->client_data = client_data;
146   async_handler_ptr->name = name;
147   if (sighandler_list.first_handler == NULL)
148     sighandler_list.first_handler = async_handler_ptr;
149   else
150     sighandler_list.last_handler->next_handler = async_handler_ptr;
151   sighandler_list.last_handler = async_handler_ptr;
152   return async_handler_ptr;
153 }
154 
155 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
156    will be used when the handlers are invoked, after we have waited
157    for some event.  The caller of this function is the interrupt
158    handler associated with a signal.  */
159 void
mark_async_signal_handler(async_signal_handler * async_handler_ptr)160 mark_async_signal_handler (async_signal_handler *async_handler_ptr)
161 {
162   if (debug_event_loop != debug_event_loop_kind::OFF)
163     {
164       /* This is called by signal handlers, so we print it "by hand" using
165            the async-signal-safe methods.  */
166       const char head[] = ("[event-loop] mark_async_signal_handler: marking"
167                                  "async signal handler `");
168       gdb_stdlog->write_async_safe (head, strlen (head));
169 
170       gdb_stdlog->write_async_safe (async_handler_ptr->name,
171                                             strlen (async_handler_ptr->name));
172 
173       const char tail[] = "`\n";
174       gdb_stdlog->write_async_safe (tail, strlen (tail));
175     }
176 
177   async_handler_ptr->ready = 1;
178   serial_event_set (async_signal_handlers_serial_event);
179 }
180 
181 /* See event-loop.h.  */
182 
183 void
clear_async_signal_handler(async_signal_handler * async_handler_ptr)184 clear_async_signal_handler (async_signal_handler *async_handler_ptr)
185 {
186   event_loop_debug_printf ("clearing async signal handler `%s`",
187                                  async_handler_ptr->name);
188   async_handler_ptr->ready = 0;
189 }
190 
191 /* See event-loop.h.  */
192 
193 int
async_signal_handler_is_marked(async_signal_handler * async_handler_ptr)194 async_signal_handler_is_marked (async_signal_handler *async_handler_ptr)
195 {
196   return async_handler_ptr->ready;
197 }
198 
199 /* Call all the handlers that are ready.  Returns true if any was
200    indeed ready.  */
201 
202 int
invoke_async_signal_handlers(void)203 invoke_async_signal_handlers (void)
204 {
205   async_signal_handler *async_handler_ptr;
206   int any_ready = 0;
207 
208   /* We're going to handle all pending signals, so no need to wake up
209      the event loop again the next time around.  Note this must be
210      cleared _before_ calling the callbacks, to avoid races.  */
211   serial_event_clear (async_signal_handlers_serial_event);
212 
213   /* Invoke all ready handlers.  */
214 
215   while (1)
216     {
217       for (async_handler_ptr = sighandler_list.first_handler;
218              async_handler_ptr != NULL;
219              async_handler_ptr = async_handler_ptr->next_handler)
220           {
221             if (async_handler_ptr->ready)
222               break;
223           }
224       if (async_handler_ptr == NULL)
225           break;
226       any_ready = 1;
227       async_handler_ptr->ready = 0;
228       /* Async signal handlers have no connection to whichever was the
229            current UI, and thus always run on the main one.  */
230       current_ui = main_ui;
231       event_loop_debug_printf ("invoking async signal handler `%s`",
232                                      async_handler_ptr->name);
233       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
234     }
235 
236   return any_ready;
237 }
238 
239 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
240    Free the space allocated for it.  */
241 void
delete_async_signal_handler(async_signal_handler ** async_handler_ptr)242 delete_async_signal_handler (async_signal_handler ** async_handler_ptr)
243 {
244   async_signal_handler *prev_ptr;
245 
246   if (sighandler_list.first_handler == (*async_handler_ptr))
247     {
248       sighandler_list.first_handler = (*async_handler_ptr)->next_handler;
249       if (sighandler_list.first_handler == NULL)
250           sighandler_list.last_handler = NULL;
251     }
252   else
253     {
254       prev_ptr = sighandler_list.first_handler;
255       while (prev_ptr && prev_ptr->next_handler != (*async_handler_ptr))
256           prev_ptr = prev_ptr->next_handler;
257       gdb_assert (prev_ptr);
258       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
259       if (sighandler_list.last_handler == (*async_handler_ptr))
260           sighandler_list.last_handler = prev_ptr;
261     }
262   xfree ((*async_handler_ptr));
263   (*async_handler_ptr) = NULL;
264 }
265 
266 /* See async-event.h.  */
267 
268 async_event_handler *
create_async_event_handler(async_event_handler_func * proc,gdb_client_data client_data,const char * name)269 create_async_event_handler (async_event_handler_func *proc,
270                                   gdb_client_data client_data,
271                                   const char *name)
272 {
273   async_event_handler *h;
274 
275   h = XNEW (struct async_event_handler);
276   h->ready = 0;
277   h->next_handler = NULL;
278   h->proc = proc;
279   h->client_data = client_data;
280   h->name = name;
281   if (async_event_handler_list.first_handler == NULL)
282     async_event_handler_list.first_handler = h;
283   else
284     async_event_handler_list.last_handler->next_handler = h;
285   async_event_handler_list.last_handler = h;
286   return h;
287 }
288 
289 /* Mark the handler (ASYNC_HANDLER_PTR) as ready.  This information
290    will be used by gdb_do_one_event.  The caller will be whoever
291    created the event source, and wants to signal that the event is
292    ready to be handled.  */
293 void
mark_async_event_handler(async_event_handler * async_handler_ptr)294 mark_async_event_handler (async_event_handler *async_handler_ptr)
295 {
296   event_loop_debug_printf ("marking async event handler `%s` "
297                                  "(previous state was %d)",
298                                  async_handler_ptr->name,
299                                  async_handler_ptr->ready);
300   async_handler_ptr->ready = 1;
301 }
302 
303 /* See event-loop.h.  */
304 
305 void
clear_async_event_handler(async_event_handler * async_handler_ptr)306 clear_async_event_handler (async_event_handler *async_handler_ptr)
307 {
308   event_loop_debug_printf ("clearing async event handler `%s`",
309                                  async_handler_ptr->name);
310   async_handler_ptr->ready = 0;
311 }
312 
313 /* See event-loop.h.  */
314 
315 bool
async_event_handler_marked(async_event_handler * handler)316 async_event_handler_marked (async_event_handler *handler)
317 {
318   return handler->ready;
319 }
320 
321 /* Check if asynchronous event handlers are ready, and call the
322    handler function for one that is.  */
323 
324 int
check_async_event_handlers()325 check_async_event_handlers ()
326 {
327   async_event_handler *async_handler_ptr;
328 
329   for (async_handler_ptr = async_event_handler_list.first_handler;
330        async_handler_ptr != NULL;
331        async_handler_ptr = async_handler_ptr->next_handler)
332     {
333       if (async_handler_ptr->ready)
334           {
335             event_loop_debug_printf ("invoking async event handler `%s`",
336                                            async_handler_ptr->name);
337             (*async_handler_ptr->proc) (async_handler_ptr->client_data);
338             return 1;
339           }
340     }
341 
342   return 0;
343 }
344 
345 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR).
346    Free the space allocated for it.  */
347 void
delete_async_event_handler(async_event_handler ** async_handler_ptr)348 delete_async_event_handler (async_event_handler **async_handler_ptr)
349 {
350   async_event_handler *prev_ptr;
351 
352   if (async_event_handler_list.first_handler == *async_handler_ptr)
353     {
354       async_event_handler_list.first_handler
355           = (*async_handler_ptr)->next_handler;
356       if (async_event_handler_list.first_handler == NULL)
357           async_event_handler_list.last_handler = NULL;
358     }
359   else
360     {
361       prev_ptr = async_event_handler_list.first_handler;
362       while (prev_ptr && prev_ptr->next_handler != *async_handler_ptr)
363           prev_ptr = prev_ptr->next_handler;
364       gdb_assert (prev_ptr);
365       prev_ptr->next_handler = (*async_handler_ptr)->next_handler;
366       if (async_event_handler_list.last_handler == (*async_handler_ptr))
367           async_event_handler_list.last_handler = prev_ptr;
368     }
369   xfree (*async_handler_ptr);
370   *async_handler_ptr = NULL;
371 }
372