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