import gdb-1999-05-25 snapshot
[platform/upstream/binutils.git] / gdb / event-loop.c
1 /* Event loop machinery for GDB, the GNU debugger.
2    Copyright 1999 Free Software Foundation, Inc.
3    Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "event-loop.h"
22 #include <readline/readline.h>
23 #include <setjmp.h>
24 #include "top.h"
25
26 /* For config.h which may define HAVE_POLL */
27 #include "defs.h"
28
29 #ifdef HAVE_POLL
30 #include <sys/poll.h>
31 #endif
32 #include <errno.h>
33
34 /* Event queue:  
35    - the first event in the queue is the head of the queue. 
36    It will be the next to be serviced.
37    - the last event in the queue 
38
39    Events can be inserted at the front of the queue or at the end of
40    the queue.  Events will be extracted from the queue for processing
41    starting from the head.  Therefore, events inserted at the head of
42    the queue will be processed in a last in first out fashoin, while
43    those inserted at the tail of the queue will be processed in a first
44    in first out manner.  All the fields are NULL if the queue is
45    empty. */
46
47 static struct
48   {
49     gdb_event *first_event;     /* First pending event */
50     gdb_event *last_event;      /* Last pending event */
51   }
52 event_queue;
53
54 /* Gdb_notifier is just a list of file descriptors gdb is interested in.
55    These are the input file descriptor, and the target file
56    descriptor. We have two flavors of the notifier, one for platforms
57    that have the POLL function, the other for those that don't, and
58    only support SELECT. Each of the elements in the gdb_notifier list is
59    basically a description of what kind of events gdb is interested
60    in, for each fd. */
61
62 /* As of 1999-04-30 only the input file descriptor is registered with the
63    event loop. */
64
65 #ifdef HAVE_POLL
66 /* Poll based implementation of the notifier. */
67
68 static struct
69   {
70     /* Ptr to head of file handler list. */
71     file_handler *first_file_handler;
72
73     /* Ptr to array of pollfd structures. */
74     struct pollfd *poll_fds;
75
76     /* Number of file descriptors to monitor. */
77     int num_fds;
78
79   }
80 gdb_notifier;
81
82 #else /* ! HAVE_POLL */
83
84 /* Select based implementation of the notifier. */
85
86 static struct
87   {
88     /* Ptr to head of file handler list. */
89     file_handler *first_file_handler;
90
91     /* Masks to be used in the next call to select.
92        Bits are set in response to calls to create_file_handler. */
93     fd_mask check_masks[3 * MASK_SIZE];
94
95     /* What file descriptors were found ready by select. */
96     fd_mask ready_masks[3 * MASK_SIZE];
97
98     /* Number of valid bits (highest fd value + 1). */
99     int num_fds;
100
101   }
102 gdb_notifier;
103
104 #endif /* HAVE_POLL */
105
106 /* All the async_signal_handlers gdb is interested in are kept onto
107    this list. */
108 static struct
109   {
110     /* Pointer to first in handler list. */
111     async_signal_handler *first_handler;     
112     
113     /* Pointer to last in handler list. */
114     async_signal_handler *last_handler;      
115   }
116 sighandler_list;
117
118 /* Is any of the handlers ready?  Check this variable using
119    check_async_ready. This is used by process_event, to determine
120    whether or not to invoke the invoke_async_signal_handler
121    function. */
122 static int async_handler_ready = 0;
123
124 static void invoke_async_signal_handler PARAMS ((void));
125 static int gdb_wait_for_event PARAMS ((void));
126 static int check_async_ready PARAMS ((void));
127 \f
128
129 /* Insert an event object into the gdb event queue at 
130    the specified position.
131    POSITION can be head or tail, with values TAIL, HEAD.
132    EVENT_PTR points to the event to be inserted into the queue.
133    The caller must allocate memory for the event. It is freed
134    after the event has ben handled.
135    Events in the queue will be processed head to tail, therefore,
136    events inserted at the head of the queue will be processed
137    as last in first out. Event appended at the tail of the queue
138    will be processed first in first out. */
139 static void
140 async_queue_event (event_ptr, position)
141      gdb_event *event_ptr;
142      queue_position position;
143 {
144   if (position == TAIL)
145     {
146       /* The event will become the new last_event. */
147
148       event_ptr->next_event = NULL;
149       if (event_queue.first_event == NULL)
150         event_queue.first_event = event_ptr;
151       else
152         event_queue.last_event->next_event = event_ptr;
153       event_queue.last_event = event_ptr;
154     }
155   else if (position == HEAD)
156     {
157       /* The event becomes the new first_event. */
158
159       event_ptr->next_event = event_queue.first_event;
160       if (event_queue.first_event == NULL)
161         event_queue.last_event = event_ptr;
162       event_queue.first_event = event_ptr;
163     }
164 }
165
166 /* Process one event.
167    The event can be the next one to be serviced in the event queue,
168    or an asynchronous event handler can be invoked in response to
169    the reception of a signal.
170    If an event was processed (either way), 1 is returned otherwise
171    0 is returned.   
172    Scan the queue from head to tail, processing therefore the high
173    priority events first, by invoking the associated event handler
174    procedure. */
175 static int
176 process_event ()
177 {
178   gdb_event *event_ptr, *prev_ptr;
179   event_handler_func *proc;
180   int fd;
181
182   /* First let's see if there are any asynchronous event handlers that
183      are ready. These would be the result of invoking any of the
184      signal handlers. */
185
186   if (check_async_ready ())
187     {
188       invoke_async_signal_handler ();
189       return 1;
190     }
191
192   /* Look in the event queue to find an event that is ready
193      to be processed. */
194
195   for (event_ptr = event_queue.first_event; event_ptr != NULL;
196        event_ptr = event_ptr->next_event)
197     {
198       /* Call the handler for the event. */
199
200       proc = event_ptr->proc;
201       fd = event_ptr->fd;
202
203       /* Let's get rid of the event from the event queue.  We need to
204          do this now because while processing the event, the proc
205          function could end up calling 'error' and therefore jump out
206          to the caller of this function, gdb_do_one_event. In that
207          case, we would have on the event queue an event wich has been
208          processed, but not deleted. */
209
210       if (event_queue.first_event == event_ptr)
211         {
212           event_queue.first_event = event_ptr->next_event;
213           if (event_ptr->next_event == NULL)
214             event_queue.last_event = NULL;
215         }
216       else
217         {
218           prev_ptr = event_queue.first_event;
219           while (prev_ptr->next_event != event_ptr)
220             prev_ptr = prev_ptr->next_event;
221
222           prev_ptr->next_event = event_ptr->next_event;
223           if (event_ptr->next_event == NULL)
224             event_queue.last_event = prev_ptr;
225         }
226       free ((char *) event_ptr);
227
228       /* Now call the procedure associted with the event. */
229       (*proc) (fd);
230       return 1;
231     }
232
233   /* this is the case if there are no event on the event queue. */
234   return 0;
235 }
236
237 /* Process one high level event.  If nothing is ready at this time,
238    wait for something to happen (via gdb_wait_for_event), then process
239    it.  Returns 1 if something was done otherwise returns 0 (this can
240    happen if there are no event sources to wait for). */
241 int
242 gdb_do_one_event ()
243 {
244   int result = 0;
245
246   while (1)
247     {
248       if (!SET_TOP_LEVEL ())
249         {
250           /* Any events already waiting in the queue? */
251           if (process_event ())
252             {
253               result = 1;
254               break;
255             }
256
257           /* Wait for a new event.  If gdb_wait_for_event returns -1,
258              we should get out because this means that there are no
259              event sources left. This will make the event loop stop,
260              and the application exit. */
261
262           result = gdb_wait_for_event ();
263           if (result < 0)
264             {
265               result = 0;
266               break;
267             }
268
269           /* Handle any new events occurred while waiting. */
270           if (process_event ())
271             {
272               result = 1;
273               break;
274             }
275
276           /* If gdb_wait_for_event has returned 1, it means that one
277              event has been handled. We break out of the loop. */
278           if (result)
279             break;
280         }                       /* end of if !set_top_level */
281       else
282         {
283           display_gdb_prompt (0);
284           /* Maybe better to set a flag to be checked somewhere as to
285              whether display the prompt or not. */
286         }
287     }
288   return result;
289 }
290 \f
291
292 /* Add a file handler/descriptor to the list of descriptors we are
293    interested in.  
294    FD is the file descriptor for the file/stream to be listened to.  
295    For the poll case, MASK is a combination (OR) of
296    POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM,
297    POLLWRBAND: these are the events we are interested in. If any of them 
298    occurs, proc should be called.
299    For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION.
300    PROC is the procedure that will be called when an event occurs for
301    FD.  CLIENT_DATA is the argument to pass to PROC. */
302 void
303 create_file_handler (fd, mask, proc, client_data)
304      int fd;
305      int mask;
306      file_handler_func *proc;
307      gdb_client_data client_data;
308 {
309   file_handler *file_ptr;
310
311 #ifndef HAVE_POLL
312   int index, bit;
313 #endif
314
315   /* Do we already have a file handler for this file? (We may be
316      changing its associated procedure). */
317   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
318        file_ptr = file_ptr->next_file)
319     {
320       if (file_ptr->fd == fd)
321         break;
322     }
323
324   /* It is a new file descriptor. */
325   if (file_ptr == NULL)
326     {
327       file_ptr = (file_handler *) xmalloc (sizeof (file_handler));
328       file_ptr->fd = fd;
329       file_ptr->ready_mask = 0;
330       file_ptr->next_file = gdb_notifier.first_file_handler;
331       gdb_notifier.first_file_handler = file_ptr;
332     }
333   file_ptr->proc = proc;
334   file_ptr->client_data = client_data;
335   file_ptr->mask = mask;
336
337 #ifdef HAVE_POLL
338
339   gdb_notifier.num_fds++;
340   gdb_notifier.poll_fds =
341     (struct pollfd *) realloc (gdb_notifier.poll_fds,
342                            (gdb_notifier.num_fds) * sizeof (struct pollfd));
343   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
344   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
345   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
346
347 #else /* ! HAVE_POLL */
348
349   index = fd / (NBBY * sizeof (fd_mask));
350   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
351
352   if (mask & GDB_READABLE)
353     gdb_notifier.check_masks[index] |= bit;
354   else
355     gdb_notifier.check_masks[index] &= ~bit;
356
357   if (mask & GDB_WRITABLE)
358     (gdb_notifier.check_masks + MASK_SIZE)[index] |= bit;
359   else
360     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
361
362   if (mask & GDB_EXCEPTION)
363     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] |= bit;
364   else
365     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
366
367   if (gdb_notifier.num_fds <= fd)
368     gdb_notifier.num_fds = fd + 1;
369
370 #endif /* HAVE_POLL */
371 }
372
373 /* Remove the file descriptor FD from the list of monitored fd's: 
374    i.e. we don't care anymore about events on the FD. */
375 void
376 delete_file_handler (fd)
377      int fd;
378 {
379   file_handler *file_ptr, *prev_ptr = NULL;
380   int i, j;
381   struct pollfd *new_poll_fds;
382 #ifndef HAVE_POLL
383   int index, bit;
384   unsigned long flags;
385 #endif
386
387   /* Find the entry for the given file. */
388
389   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
390        file_ptr = file_ptr->next_file)
391     {
392       if (file_ptr->fd == fd)
393         break;
394     }
395
396   if (file_ptr == NULL)
397     return;
398
399   /* Deactivate the file descriptor, by clearing its mask, 
400      so that it will not fire again. */
401
402   file_ptr->mask = 0;
403
404 #ifdef HAVE_POLL
405   /* Create a new poll_fds array by copying every fd's information but the
406      one we want to get rid of. */
407
408   new_poll_fds =
409     (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
410
411   for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
412     {
413       if ((gdb_notifier.poll_fds + i)->fd != fd)
414         {
415           (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
416           (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
417           (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents;
418           j++;
419         }
420     }
421   free (gdb_notifier.poll_fds);
422   gdb_notifier.poll_fds = new_poll_fds;
423   gdb_notifier.num_fds--;
424
425 #else /* ! HAVE_POLL */
426
427   index = fd / (NBBY * sizeof (fd_mask));
428   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
429
430   if (file_ptr->mask & GDB_READABLE)
431     gdb_notifier.check_masks[index] &= ~bit;
432   if (file_ptr->mask & GDB_WRITABLE)
433     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
434   if (file_ptr->mask & GDB_EXCEPTION)
435     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
436
437   /* Find current max fd. */
438
439   if ((fd + 1) == gdb_notifier.num_fds)
440     {
441       for (gdb_notifier.num_fds = 0; index >= 0; index--)
442         {
443           flags = gdb_notifier.check_masks[index]
444             | (gdb_notifier.check_masks + MASK_SIZE)[index]
445             | (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index];
446           if (flags)
447             {
448               for (i = (NBBY * sizeof (fd_mask)); i > 0; i--)
449                 {
450                   if (flags & (((unsigned long) 1) << (i - 1)))
451                     break;
452                 }
453               gdb_notifier.num_fds = index * (NBBY * sizeof (fd_mask)) + i;
454               break;
455             }
456         }
457     }
458 #endif /* HAVE_POLL */
459
460   /* Get rid of the file handler in the file handler list. */
461   if (file_ptr == gdb_notifier.first_file_handler)
462     gdb_notifier.first_file_handler = file_ptr->next_file;
463   else
464     {
465       for (prev_ptr = gdb_notifier.first_file_handler;
466            prev_ptr->next_file == file_ptr;
467            prev_ptr = prev_ptr->next_file)
468         ;
469       prev_ptr->next_file = file_ptr->next_file;
470     }
471   free ((char *) file_ptr);
472 }
473
474 /* Handle the given event by calling the procedure associated to the
475    corresponding file handler.  Called by process_event indirectly,
476    through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
477    event in the front of the event queue. */
478 static void
479 handle_file_event (event_file_desc)
480      int event_file_desc;
481 {
482   file_handler *file_ptr;
483   int mask, error_mask;
484
485   /* Search the file handler list to find one that matches the fd in
486      the event. */
487   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
488        file_ptr = file_ptr->next_file)
489     {
490       if (file_ptr->fd == event_file_desc)
491         {
492           /* With poll, the ready_mask could have any of three events
493              set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot
494              be used in the requested event mask (events), but they
495              can be returned in the return mask (revents). We need to
496              check for those event too, and add them to the mask which
497              will be passed to the handler. */
498
499           /* See if the desired events (mask) match the received
500              events (ready_mask). */
501
502 #ifdef HAVE_POLL
503           error_mask = POLLHUP | POLLERR | POLLNVAL;
504           mask = (file_ptr->ready_mask & file_ptr->mask) |
505             (file_ptr->ready_mask & error_mask);
506
507 #else /* ! HAVE_POLL */
508           mask = file_ptr->ready_mask & file_ptr->mask;
509 #endif /* HAVE_POLL */
510
511           /* Clear the received events for next time around. */
512           file_ptr->ready_mask = 0;
513
514           /* If there was a match, then call the handler. */
515           if (mask != 0)
516             (*file_ptr->proc) (file_ptr->client_data, mask);
517           break;
518         }
519     }
520 }
521
522 /* Called by gdb_do_one_event to wait for new events on the 
523    monitored file descriptors. Queue file events as they are 
524    detected by the poll. 
525    If there are no events, this function will block in the 
526    call to poll.
527    Return -1 if there are no files descriptors to monitor, 
528    otherwise return 0. */
529 static int
530 gdb_wait_for_event ()
531 {
532   file_handler *file_ptr;
533   gdb_event *file_event_ptr;
534   int num_found, i;
535
536 #ifndef HAVE_POLL
537   int mask, bit, index;
538 #endif
539
540   if (gdb_notifier.num_fds == 0)
541     return -1;
542
543 #ifdef HAVE_POLL
544   num_found =
545     poll (gdb_notifier.poll_fds, (unsigned long) gdb_notifier.num_fds, -1);
546
547 #else /* ! HAVE_POLL */
548   memcpy (gdb_notifier.ready_masks,
549           gdb_notifier.check_masks,
550           3 * MASK_SIZE * sizeof (fd_mask));
551   num_found = select (gdb_notifier.num_fds,
552                       (SELECT_MASK *) & gdb_notifier.ready_masks[0],
553                       (SELECT_MASK *) & gdb_notifier.ready_masks[MASK_SIZE],
554                   (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE],
555                       NULL);
556
557   /* Clear the masks after an error from select. */
558   if (num_found == -1)
559     memset (gdb_notifier.ready_masks,
560             0, 3 * MASK_SIZE * sizeof (fd_mask));
561
562 #endif /* HAVE_POLL */
563
564   /* Enqueue all detected file events. */
565
566 #ifdef HAVE_POLL
567
568   for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++)
569     {
570       if ((gdb_notifier.poll_fds + i)->revents)
571         num_found--;
572       else
573         continue;
574
575       for (file_ptr = gdb_notifier.first_file_handler;
576            file_ptr != NULL;
577            file_ptr = file_ptr->next_file)
578         {
579           if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
580             break;
581         }
582
583       if (file_ptr)
584         {
585           /* Enqueue an event only if this is still a new event for
586              this fd. */
587           if (file_ptr->ready_mask == 0)
588             {
589               file_event_ptr =
590                 (gdb_event *) xmalloc (sizeof (gdb_event));
591               file_event_ptr->proc = handle_file_event;
592               file_event_ptr->fd = file_ptr->fd;
593               async_queue_event (file_event_ptr, TAIL);
594             }
595         }
596
597       file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents;
598     }
599
600 #else /* ! HAVE_POLL */
601   for (file_ptr = gdb_notifier.first_file_handler;
602        (file_ptr != NULL) && (num_found > 0);
603        file_ptr = file_ptr->next_file)
604     {
605       index = file_ptr->fd / (NBBY * sizeof (fd_mask));
606       bit = 1 << (file_ptr->fd % (NBBY * sizeof (fd_mask)));
607       mask = 0;
608
609       if (gdb_notifier.ready_masks[index] & bit)
610         mask |= GDB_READABLE;
611       if ((gdb_notifier.ready_masks + MASK_SIZE)[index] & bit)
612         mask |= GDB_WRITABLE;
613       if ((gdb_notifier.ready_masks + 2 * (MASK_SIZE))[index] & bit)
614         mask |= GDB_EXCEPTION;
615
616       if (!mask)
617         continue;
618       else
619         num_found--;
620
621       /* Enqueue an event only if this is still a new event for
622          this fd. */
623
624       if (file_ptr->ready_mask == 0)
625         {
626           file_event_ptr =
627             (gdb_event *) xmalloc (sizeof (gdb_event));
628           file_event_ptr->proc = handle_file_event;
629           file_event_ptr->fd = file_ptr->fd;
630           async_queue_event (file_event_ptr, TAIL);
631         }
632       file_ptr->ready_mask = mask;
633     }
634 #endif /* HAVE_POLL */
635
636   return 0;
637 }
638 \f
639
640 /* Create an asynchronous handler, allocating memory for it. 
641    Return a pointer to the newly created handler.
642    This pointer will be used to invoke the handler by 
643    invoke_async_signal_handler.
644    PROC is the function to call with CLIENT_DATA argument 
645    whenever the handler is invoked. */
646 async_signal_handler *
647 create_async_signal_handler (proc, client_data)
648      async_handler_func *proc;
649      gdb_client_data client_data;
650 {
651   async_signal_handler *async_handler_ptr;
652
653   async_handler_ptr =
654     (async_signal_handler *) xmalloc (sizeof (async_signal_handler));
655   async_handler_ptr->ready = 0;
656   async_handler_ptr->next_handler = NULL;
657   async_handler_ptr->proc = proc;
658   async_handler_ptr->client_data = client_data;
659   if (sighandler_list.first_handler == NULL)
660     sighandler_list.first_handler = async_handler_ptr;
661   else
662     sighandler_list.last_handler->next_handler = async_handler_ptr;
663   sighandler_list.last_handler = async_handler_ptr;
664   return async_handler_ptr;
665 }
666
667 /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information will
668    be used when the handlers are invoked, after we have waited for
669    some event.  The caller of this function is the interrupt handler
670    associated with a signal. */
671 void
672 mark_async_signal_handler (async_handler_ptr)
673      async_signal_handler *async_handler_ptr;
674 {
675   ((async_signal_handler *) async_handler_ptr)->ready = 1;
676   async_handler_ready = 1;
677 }
678
679 /* Call all the handlers that are ready. */
680 static void
681 invoke_async_signal_handler ()
682 {
683   async_signal_handler *async_handler_ptr;
684
685   if (async_handler_ready == 0)
686     return;
687   async_handler_ready = 0;
688
689   /* Invoke ready handlers. */
690
691   while (1)
692     {
693       for (async_handler_ptr = sighandler_list.first_handler; 
694            async_handler_ptr != NULL;
695            async_handler_ptr = async_handler_ptr->next_handler)
696         {
697           if (async_handler_ptr->ready)
698             break;
699         }
700       if (async_handler_ptr == NULL)
701         break;
702       async_handler_ptr->ready = 0;
703       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
704     }
705
706   return;
707 }
708
709 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 
710    Free the space allocated for it.  */
711 void
712 delete_async_signal_handler (async_handler_ptr)
713      async_signal_handler *async_handler_ptr;
714 {
715   async_signal_handler *prev_ptr;
716
717   if (sighandler_list.first_handler == async_handler_ptr)
718     {
719       sighandler_list.first_handler = async_handler_ptr->next_handler;
720       if (sighandler_list.first_handler == NULL)
721         sighandler_list.last_handler = NULL;
722     }
723   else
724     {
725       prev_ptr = sighandler_list.first_handler;
726       while (prev_ptr->next_handler != async_handler_ptr)
727         prev_ptr = prev_ptr->next_handler;
728       prev_ptr->next_handler = async_handler_ptr->next_handler;
729       if (sighandler_list.last_handler == async_handler_ptr)
730         sighandler_list.last_handler = prev_ptr;
731     }
732   free ((char *) async_handler_ptr);
733 }
734
735 /* Is it necessary to call invoke_async_signal_handler? */
736 static int
737 check_async_ready ()
738 {
739   return async_handler_ready;
740 }