import gdb-1999-05-10
[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 4/30/99 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 extern display_gdb_prompt PARAMS ((char *));
128 \f
129
130 /* Insert an event object into the gdb event queue at 
131    the specified position.
132    POSITION can be head or tail, with values TAIL, HEAD.
133    EVENT_PTR points to the event to be inserted into the queue.
134    The caller must allocate memory for the event. It is freed
135    after the event has ben handled.
136    Events in the queue will be processed head to tail, therefore,
137    events inserted at the head of the queue will be processed
138    as last in first out. Event appended at the tail of the queue
139    will be processed first in first out. */
140 static void
141 async_queue_event (event_ptr, position)
142      gdb_event *event_ptr;
143      queue_position position;
144 {
145   if (position == TAIL)
146     {
147       /* The event will become the new last_event. */
148
149       event_ptr->next_event = NULL;
150       if (event_queue.first_event == NULL)
151         event_queue.first_event = event_ptr;
152       else
153         event_queue.last_event->next_event = event_ptr;
154       event_queue.last_event = event_ptr;
155     }
156   else if (position == HEAD)
157     {
158       /* The event becomes the new first_event. */
159
160       event_ptr->next_event = event_queue.first_event;
161       if (event_queue.first_event == NULL)
162         event_queue.last_event = event_ptr;
163       event_queue.first_event = event_ptr;
164     }
165 }
166
167 /* Process one event.
168    The event can be the next one to be serviced in the event queue,
169    or an asynchronous event handler can be invoked in response to
170    the reception of a signal.
171    If an event was processed (either way), 1 is returned otherwise
172    0 is returned.   
173    Scan the queue from head to tail, processing therefore the high
174    priority events first, by invoking the associated event handler
175    procedure. */
176 static int
177 process_event ()
178 {
179   gdb_event *event_ptr, *prev_ptr;
180   event_handler_func *proc;
181   int fd;
182
183   /* First let's see if there are any asynchronous event handlers that
184      are ready. These would be the result of invoking any of the
185      signal handlers. */
186
187   if (check_async_ready ())
188     {
189       invoke_async_signal_handler ();
190       return 1;
191     }
192
193   /* Look in the event queue to find an event that is ready
194      to be processed. */
195
196   for (event_ptr = event_queue.first_event; event_ptr != NULL;
197        event_ptr = event_ptr->next_event)
198     {
199       /* Call the handler for the event. */
200
201       proc = event_ptr->proc;
202       fd = event_ptr->fd;
203
204       /* Let's get rid of the event from the event queue.  We need to
205          do this now because while processing the event, the proc
206          function could end up calling 'error' and therefore jump out
207          to the caller of this function, gdb_do_one_event. In that
208          case, we would have on the event queue an event wich has been
209          processed, but not deleted. */
210
211       if (event_queue.first_event == event_ptr)
212         {
213           event_queue.first_event = event_ptr->next_event;
214           if (event_ptr->next_event == NULL)
215             event_queue.last_event = NULL;
216         }
217       else
218         {
219           prev_ptr = event_queue.first_event;
220           while (prev_ptr->next_event != event_ptr)
221             prev_ptr = prev_ptr->next_event;
222
223           prev_ptr->next_event = event_ptr->next_event;
224           if (event_ptr->next_event == NULL)
225             event_queue.last_event = prev_ptr;
226         }
227       free ((char *) event_ptr);
228
229       /* Now call the procedure associted with the event. */
230       (*proc) (fd);
231       return 1;
232     }
233
234   /* this is the case if there are no event on the event queue. */
235   return 0;
236 }
237
238 /* Process one high level event.  If nothing is ready at this time,
239    wait for something to happen (via gdb_wait_for_event), then process
240    it.  Returns 1 if something was done otherwise returns 0 (this can
241    happen if there are no event sources to wait for). */
242 int
243 gdb_do_one_event ()
244 {
245   int result = 0;
246
247   while (1)
248     {
249       if (!SET_TOP_LEVEL ())
250         {
251           /* Any events already waiting in the queue? */
252           if (process_event ())
253             {
254               result = 1;
255               break;
256             }
257
258           /* Wait for a new event.  If gdb_wait_for_event returns -1,
259              we should get out because this means that there are no
260              event sources left. This will make the event loop stop,
261              and the application exit. */
262
263           result = gdb_wait_for_event ();
264           if (result < 0)
265             {
266               result = 0;
267               break;
268             }
269
270           /* Handle any new events occurred while waiting. */
271           if (process_event ())
272             {
273               result = 1;
274               break;
275             }
276
277           /* If gdb_wait_for_event has returned 1, it means that one
278              event has been handled. We break out of the loop. */
279           if (result)
280             break;
281         }                       /* end of if !set_top_level */
282       else
283         {
284           display_gdb_prompt (0);
285           /* Maybe better to set a flag to be checked somewhere as to
286              whether display the prompt or not. */
287         }
288     }
289   return result;
290 }
291 \f
292
293 /* Add a file handler/descriptor to the list of descriptors we are
294    interested in.  
295    FD is the file descriptor for the file/stream to be listened to.  
296    For the poll case, MASK is a combination (OR) of
297    POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM,
298    POLLWRBAND: these are the events we are interested in. If any of them 
299    occurs, proc should be called.
300    For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION.
301    PROC is the procedure that will be called when an event occurs for
302    FD.  CLIENT_DATA is the argument to pass to PROC. */
303 void
304 create_file_handler (fd, mask, proc, client_data)
305      int fd;
306      int mask;
307      file_handler_func *proc;
308      gdb_client_data client_data;
309 {
310   file_handler *file_ptr;
311
312 #ifndef HAVE_POLL
313   int index, bit;
314 #endif
315
316   /* Do we already have a file handler for this file? (We may be
317      changing its associated procedure). */
318   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
319        file_ptr = file_ptr->next_file)
320     {
321       if (file_ptr->fd == fd)
322         break;
323     }
324
325   /* It is a new file descriptor. */
326   if (file_ptr == NULL)
327     {
328       file_ptr = (file_handler *) xmalloc (sizeof (file_handler));
329       file_ptr->fd = fd;
330       file_ptr->ready_mask = 0;
331       file_ptr->next_file = gdb_notifier.first_file_handler;
332       gdb_notifier.first_file_handler = file_ptr;
333     }
334   file_ptr->proc = proc;
335   file_ptr->client_data = client_data;
336   file_ptr->mask = mask;
337
338 #ifdef HAVE_POLL
339
340   gdb_notifier.num_fds++;
341   gdb_notifier.poll_fds =
342     (struct pollfd *) realloc (gdb_notifier.poll_fds,
343                            (gdb_notifier.num_fds) * sizeof (struct pollfd));
344   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
345   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
346   (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
347
348 #else /* ! HAVE_POLL */
349
350   index = fd / (NBBY * sizeof (fd_mask));
351   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
352
353   if (mask & GDB_READABLE)
354     gdb_notifier.check_masks[index] |= bit;
355   else
356     gdb_notifier.check_masks[index] &= ~bit;
357
358   if (mask & GDB_WRITABLE)
359     (gdb_notifier.check_masks + MASK_SIZE)[index] |= bit;
360   else
361     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
362
363   if (mask & GDB_EXCEPTION)
364     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] |= bit;
365   else
366     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
367
368   if (gdb_notifier.num_fds <= fd)
369     gdb_notifier.num_fds = fd + 1;
370
371 #endif /* HAVE_POLL */
372 }
373
374 /* Remove the file descriptor FD from the list of monitored fd's: 
375    i.e. we don't care anymore about events on the FD. */
376 void
377 delete_file_handler (fd)
378      int fd;
379 {
380   file_handler *file_ptr, *prev_ptr = NULL;
381   int i, j;
382   struct pollfd *new_poll_fds;
383 #ifndef HAVE_POLL
384   int index, bit;
385   unsigned long flags;
386 #endif
387
388   /* Find the entry for the given file. */
389
390   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
391        file_ptr = file_ptr->next_file)
392     {
393       if (file_ptr->fd == fd)
394         break;
395     }
396
397   if (file_ptr == NULL)
398     return;
399
400   /* Deactivate the file descriptor, by clearing its mask, 
401      so that it will not fire again. */
402
403   file_ptr->mask = 0;
404
405 #ifdef HAVE_POLL
406   /* Create a new poll_fds array by copying every fd's information but the
407      one we want to get rid of. */
408
409   new_poll_fds =
410     (struct pollfd *) xmalloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
411
412   for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
413     {
414       if ((gdb_notifier.poll_fds + i)->fd != fd)
415         {
416           (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
417           (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
418           (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents;
419           j++;
420         }
421     }
422   free (gdb_notifier.poll_fds);
423   gdb_notifier.poll_fds = new_poll_fds;
424   gdb_notifier.num_fds--;
425
426 #else /* ! HAVE_POLL */
427
428   index = fd / (NBBY * sizeof (fd_mask));
429   bit = 1 << (fd % (NBBY * sizeof (fd_mask)));
430
431   if (file_ptr->mask & GDB_READABLE)
432     gdb_notifier.check_masks[index] &= ~bit;
433   if (file_ptr->mask & GDB_WRITABLE)
434     (gdb_notifier.check_masks + MASK_SIZE)[index] &= ~bit;
435   if (file_ptr->mask & GDB_EXCEPTION)
436     (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index] &= ~bit;
437
438   /* Find current max fd. */
439
440   if ((fd + 1) == gdb_notifier.num_fds)
441     {
442       for (gdb_notifier.num_fds = 0; index >= 0; index--)
443         {
444           flags = gdb_notifier.check_masks[index]
445             | (gdb_notifier.check_masks + MASK_SIZE)[index]
446             | (gdb_notifier.check_masks + 2 * (MASK_SIZE))[index];
447           if (flags)
448             {
449               for (i = (NBBY * sizeof (fd_mask)); i > 0; i--)
450                 {
451                   if (flags & (((unsigned long) 1) << (i - 1)))
452                     break;
453                 }
454               gdb_notifier.num_fds = index * (NBBY * sizeof (fd_mask)) + i;
455               break;
456             }
457         }
458     }
459 #endif /* HAVE_POLL */
460
461   /* Get rid of the file handler in the file handler list. */
462   if (file_ptr == gdb_notifier.first_file_handler)
463     gdb_notifier.first_file_handler = file_ptr->next_file;
464   else
465     {
466       for (prev_ptr = gdb_notifier.first_file_handler;
467            prev_ptr->next_file == file_ptr;
468            prev_ptr = prev_ptr->next_file)
469         ;
470       prev_ptr->next_file = file_ptr->next_file;
471     }
472   free ((char *) file_ptr);
473 }
474
475 /* Handle the given event by calling the procedure associated to the
476    corresponding file handler.  Called by process_event indirectly,
477    through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
478    event in the front of the event queue. */
479 static void
480 handle_file_event (event_file_desc)
481      int event_file_desc;
482 {
483   file_handler *file_ptr;
484   int mask, error_mask;
485
486   /* Search the file handler list to find one that matches the fd in
487      the event. */
488   for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
489        file_ptr = file_ptr->next_file)
490     {
491       if (file_ptr->fd == event_file_desc)
492         {
493           /* With poll, the ready_mask could have any of three events
494              set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot
495              be used in the requested event mask (events), but they
496              can be returned in the return mask (revents). We need to
497              check for those event too, and add them to the mask which
498              will be passed to the handler. */
499
500           /* See if the desired events (mask) match the received
501              events (ready_mask). */
502
503 #ifdef HAVE_POLL
504           error_mask = POLLHUP | POLLERR | POLLNVAL;
505           mask = (file_ptr->ready_mask & file_ptr->mask) |
506             (file_ptr->ready_mask & error_mask);
507
508 #else /* ! HAVE_POLL */
509           mask = file_ptr->ready_mask & file_ptr->mask;
510 #endif /* HAVE_POLL */
511
512           /* Clear the received events for next time around. */
513           file_ptr->ready_mask = 0;
514
515           /* If there was a match, then call the handler. */
516           if (mask != 0)
517             (*file_ptr->proc) (file_ptr->client_data, mask);
518           break;
519         }
520     }
521 }
522
523 /* Called by gdb_do_one_event to wait for new events on the 
524    monitored file descriptors. Queue file events as they are 
525    detected by the poll. 
526    If there are no events, this function will block in the 
527    call to poll.
528    Return -1 if there are no files descriptors to monitor, 
529    otherwise return 0. */
530 static int
531 gdb_wait_for_event ()
532 {
533   file_handler *file_ptr;
534   gdb_event *file_event_ptr;
535   int num_found, i;
536
537 #ifndef HAVE_POLL
538   int mask, bit, index;
539 #endif
540
541   if (gdb_notifier.num_fds == 0)
542     return -1;
543
544 #ifdef HAVE_POLL
545   num_found =
546     poll (gdb_notifier.poll_fds, (unsigned long) gdb_notifier.num_fds, -1);
547
548 #else /* ! HAVE_POLL */
549   memcpy (gdb_notifier.ready_masks,
550           gdb_notifier.check_masks,
551           3 * MASK_SIZE * sizeof (fd_mask));
552   num_found = select (gdb_notifier.num_fds,
553                       (SELECT_MASK *) & gdb_notifier.ready_masks[0],
554                       (SELECT_MASK *) & gdb_notifier.ready_masks[MASK_SIZE],
555                   (SELECT_MASK *) & gdb_notifier.ready_masks[2 * MASK_SIZE],
556                       NULL);
557
558   /* Clear the masks after an error from select. */
559   if (num_found == -1)
560     memset (gdb_notifier.ready_masks,
561             0, 3 * MASK_SIZE * sizeof (fd_mask));
562
563 #endif /* HAVE_POLL */
564
565   /* Enqueue all detected file events. */
566
567 #ifdef HAVE_POLL
568
569   for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++)
570     {
571       if ((gdb_notifier.poll_fds + i)->revents)
572         num_found--;
573       else
574         continue;
575
576       for (file_ptr = gdb_notifier.first_file_handler;
577            file_ptr != NULL;
578            file_ptr = file_ptr->next_file)
579         {
580           if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
581             break;
582         }
583
584       if (file_ptr)
585         {
586           /* Enqueue an event only if this is still a new event for
587              this fd. */
588           if (file_ptr->ready_mask == 0)
589             {
590               file_event_ptr =
591                 (gdb_event *) xmalloc (sizeof (gdb_event));
592               file_event_ptr->proc = handle_file_event;
593               file_event_ptr->fd = file_ptr->fd;
594               async_queue_event (file_event_ptr, TAIL);
595             }
596         }
597
598       file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents;
599     }
600
601 #else /* ! HAVE_POLL */
602   for (file_ptr = gdb_notifier.first_file_handler;
603        (file_ptr != NULL) && (num_found > 0);
604        file_ptr = file_ptr->next_file)
605     {
606       index = file_ptr->fd / (NBBY * sizeof (fd_mask));
607       bit = 1 << (file_ptr->fd % (NBBY * sizeof (fd_mask)));
608       mask = 0;
609
610       if (gdb_notifier.ready_masks[index] & bit)
611         mask |= GDB_READABLE;
612       if ((gdb_notifier.ready_masks + MASK_SIZE)[index] & bit)
613         mask |= GDB_WRITABLE;
614       if ((gdb_notifier.ready_masks + 2 * (MASK_SIZE))[index] & bit)
615         mask |= GDB_EXCEPTION;
616
617       if (!mask)
618         continue;
619       else
620         num_found--;
621
622       /* Enqueue an event only if this is still a new event for
623          this fd. */
624
625       if (file_ptr->ready_mask == 0)
626         {
627           file_event_ptr =
628             (gdb_event *) xmalloc (sizeof (gdb_event));
629           file_event_ptr->proc = handle_file_event;
630           file_event_ptr->fd = file_ptr->fd;
631           async_queue_event (file_event_ptr, TAIL);
632         }
633       file_ptr->ready_mask = mask;
634     }
635 #endif /* HAVE_POLL */
636
637   return 0;
638 }
639 \f
640
641 /* Create an asynchronous handler, allocating memory for it. 
642    Return a pointer to the newly created handler.
643    This pointer will be used to invoke the handler by 
644    invoke_async_signal_handler.
645    PROC is the function to call with CLIENT_DATA argument 
646    whenever the handler is invoked. */
647 async_signal_handler *
648 create_async_signal_handler (proc, client_data)
649      async_handler_func *proc;
650      gdb_client_data client_data;
651 {
652   async_signal_handler *async_handler_ptr;
653
654   async_handler_ptr =
655     (async_signal_handler *) xmalloc (sizeof (async_signal_handler));
656   async_handler_ptr->ready = 0;
657   async_handler_ptr->next_handler = NULL;
658   async_handler_ptr->proc = proc;
659   async_handler_ptr->client_data = client_data;
660   if (sighandler_list.first_handler == NULL)
661     sighandler_list.first_handler = async_handler_ptr;
662   else
663     sighandler_list.last_handler->next_handler = async_handler_ptr;
664   sighandler_list.last_handler = async_handler_ptr;
665   return async_handler_ptr;
666 }
667
668 /* Mark the handler (ASYNC_HANDLER_PTR) as ready. This information will
669    be used when the handlers are invoked, after we have waited for
670    some event.  The caller of this function is the interrupt handler
671    associated with a signal. */
672 void
673 mark_async_signal_handler (async_handler_ptr)
674      async_signal_handler *async_handler_ptr;
675 {
676   ((async_signal_handler *) async_handler_ptr)->ready = 1;
677   async_handler_ready = 1;
678 }
679
680 /* Call all the handlers that are ready. */
681 static void
682 invoke_async_signal_handler ()
683 {
684   async_signal_handler *async_handler_ptr;
685
686   if (async_handler_ready == 0)
687     return;
688   async_handler_ready = 0;
689
690   /* Invoke ready handlers. */
691
692   while (1)
693     {
694       for (async_handler_ptr = sighandler_list.first_handler; 
695            async_handler_ptr != NULL;
696            async_handler_ptr = async_handler_ptr->next_handler)
697         {
698           if (async_handler_ptr->ready)
699             break;
700         }
701       if (async_handler_ptr == NULL)
702         break;
703       async_handler_ptr->ready = 0;
704       (*async_handler_ptr->proc) (async_handler_ptr->client_data);
705     }
706
707   return;
708 }
709
710 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 
711    Free the space allocated for it.  */
712 void
713 delete_async_signal_handler (async_handler_ptr)
714      async_signal_handler *async_handler_ptr;
715 {
716   async_signal_handler *prev_ptr;
717
718   if (sighandler_list.first_handler == async_handler_ptr)
719     {
720       sighandler_list.first_handler = async_handler_ptr->next_handler;
721       if (sighandler_list.first_handler == NULL)
722         sighandler_list.last_handler = NULL;
723     }
724   else
725     {
726       prev_ptr = sighandler_list.first_handler;
727       while (prev_ptr->next_handler != async_handler_ptr)
728         prev_ptr = prev_ptr->next_handler;
729       prev_ptr->next_handler = async_handler_ptr->next_handler;
730       if (sighandler_list.last_handler == async_handler_ptr)
731         sighandler_list.last_handler = prev_ptr;
732     }
733   free ((char *) async_handler_ptr);
734 }
735
736 /* Is it necessary to call invoke_async_signal_handler? */
737 static int
738 check_async_ready ()
739 {
740   return async_handler_ready;
741 }