/[guile]/guile/guile-core/libguile/scmsigs.c
ViewVC logotype

Diff of /guile/guile-core/libguile/scmsigs.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.69 by xxhanwen, Sat Jul 20 14:08:34 2002 UTC revision 1.70 by mvo, Fri Oct 4 14:13:26 2002 UTC
# Line 1  Line 1 
1  /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc.  /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc.
2   *   *
3   * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
4   * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
# Line 102  int usleep (); Line 102  int usleep ();
102    
103    
104  /* take_signal is installed as the C signal handler whenever a Scheme  /* take_signal is installed as the C signal handler whenever a Scheme
105     handler is set.  when a signal arrives, take_signal marks the corresponding     handler is set.  when a signal arrives, take_signal will queue the
106     element of got_signal and marks signal_async.  the thunk in signal_async     Scheme handler procedure for its thread.  */
    (sys_deliver_signals) will be run at the next opportunity, outside a  
    critical section. sys_deliver_signals runs each Scheme handler for  
    which got_signal is set.  */  
107    
 static SCM signal_async;  
108    
109  static char got_signal[NSIG];  /* Scheme vectors with information about a signal.  signal_handlers
110       contains the handler procedure or #f, signal_handler_cells contains
111  /* a Scheme vector of handler procedures.  */     preallocated cells for queuing the handler in take_signal since we
112       can't allocate during signal delivery, signal_handler_threads
113       points to the thread that a signal should be delivered to.
114    */
115  static SCM *signal_handlers;  static SCM *signal_handlers;
116    static SCM signal_handler_cells;
117    static SCM signal_handler_threads;
118    
119  /* saves the original C handlers, when a new handler is installed.  /* saves the original C handlers, when a new handler is installed.
120     set to SIG_ERR if the original handler is installed.  */     set to SIG_ERR if the original handler is installed.  */
# Line 126  static SIGRETTYPE (*orig_handlers[NSIG]) Line 127  static SIGRETTYPE (*orig_handlers[NSIG])
127  static SIGRETTYPE  static SIGRETTYPE
128  take_signal (int signum)  take_signal (int signum)
129  {  {
130    got_signal[signum] = 1;    if (signum >= 0 && signum < NSIG)
131    scm_system_async_mark_from_signal_handler (signal_async);      {
132          SCM thread = SCM_VECTOR_REF (signal_handler_threads, signum);
133          scm_i_queue_async_cell (SCM_VECTOR_REF(signal_handler_cells, signum),
134                                  scm_i_thread_root (thread));
135        }
136    #ifndef HAVE_SIGACTION
137      signal (signum, take_signal);
138    #endif
139  }  }
140    
141  static SCM  SCM
142  sys_deliver_signals (void)  scm_sigaction (SCM signum, SCM handler, SCM flags)
143  {  {
144    int i;    return scm_sigaction_for_thread (signum, handler, flags, SCM_UNDEFINED);
145    }
146    
147    for (i = 0; i < NSIG; i++)  static SCM
148      {  close_1 (SCM proc, SCM arg)
149        if (got_signal[i])  {
150          {    return scm_primitive_eval_x (scm_list_3 (scm_sym_lambda, SCM_EOL,
151            /* The flag is reset before calling the handler in case the                                             scm_list_2 (proc, arg)));
              handler doesn't return.  If the handler doesn't return  
              but leaves other signals flagged, they their handlers  
              will be applied some time later when the async is checked  
              again.  It would probably be better to reset the flags  
              after doing a longjmp.  */  
           got_signal[i] = 0;  
 #ifndef HAVE_SIGACTION  
           signal (i, take_signal);  
 #endif  
           scm_call_1 (SCM_VELTS (*signal_handlers)[i], SCM_MAKINUM (i));  
         }  
     }  
   return SCM_UNSPECIFIED;  
152  }  }
153    
154  /* user interface for installation of signal handlers.  */  /* user interface for installation of signal handlers.  */
155  SCM_DEFINE (scm_sigaction, "sigaction", 1, 2, 0,  SCM_DEFINE (scm_sigaction_for_thread, "sigaction", 1, 3, 0,
156             (SCM signum, SCM handler, SCM flags),             (SCM signum, SCM handler, SCM flags, SCM thread),
157              "Install or report the signal handler for a specified signal.\n\n"              "Install or report the signal handler for a specified signal.\n\n"
158              "@var{signum} is the signal number, which can be specified using the value\n"              "@var{signum} is the signal number, which can be specified using the value\n"
159              "of variables such as @code{SIGINT}.\n\n"              "of variables such as @code{SIGINT}.\n\n"
160              "If @var{action} is omitted, @code{sigaction} returns a pair: the\n"              "If @var{handler} is omitted, @code{sigaction} returns a pair: the\n"
161              "CAR is the current\n"              "CAR is the current\n"
162              "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"              "signal hander, which will be either an integer with the value @code{SIG_DFL}\n"
163              "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"              "(default action) or @code{SIG_IGN} (ignore), or the Scheme procedure which\n"
164              "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"              "handles the signal, or @code{#f} if a non-Scheme procedure handles the\n"
165              "signal.  The CDR contains the current @code{sigaction} flags for the handler.\n\n"              "signal.  The CDR contains the current @code{sigaction} flags for the handler.\n\n"
166              "If @var{action} is provided, it is installed as the new handler for\n"              "If @var{handler} is provided, it is installed as the new handler for\n"
167              "@var{signum}.  @var{action} can be a Scheme procedure taking one\n"              "@var{signum}.  @var{handler} can be a Scheme procedure taking one\n"
168              "argument, or the value of @code{SIG_DFL} (default action) or\n"              "argument, or the value of @code{SIG_DFL} (default action) or\n"
169              "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"              "@code{SIG_IGN} (ignore), or @code{#f} to restore whatever signal handler\n"
170              "was installed before @code{sigaction} was first used.  Flags can\n"              "was installed before @code{sigaction} was first used.  When\n"
171                "a scheme procedure has been specified, that procedure will run\n"
172                "in the given @var{thread}.   When no thread has been given, the\n"
173                "thread that made this call to @code{sigaction} is used.\n"
174                "Flags can "
175              "optionally be specified for the new handler (@code{SA_RESTART} will\n"              "optionally be specified for the new handler (@code{SA_RESTART} will\n"
176              "always be added if it's available and the system is using restartable\n"              "always be added if it's available and the system is using restartable\n"
177              "system calls.)  The return value is a pair with information about the\n"              "system calls.)  The return value is a pair with information about the\n"
# Line 180  SCM_DEFINE (scm_sigaction, "sigaction", Line 180  SCM_DEFINE (scm_sigaction, "sigaction",
180              "facility.  Maybe this is not needed, since the thread support may\n"              "facility.  Maybe this is not needed, since the thread support may\n"
181              "provide solutions to the problem of consistent access to data\n"              "provide solutions to the problem of consistent access to data\n"
182              "structures.")              "structures.")
183  #define FUNC_NAME s_scm_sigaction  #define FUNC_NAME s_scm_sigaction_for_thread
184  {  {
185    int csig;    int csig;
186  #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
# Line 196  SCM_DEFINE (scm_sigaction, "sigaction", Line 196  SCM_DEFINE (scm_sigaction, "sigaction",
196    SCM old_handler;    SCM old_handler;
197    
198    SCM_VALIDATE_INUM_COPY (1, signum, csig);    SCM_VALIDATE_INUM_COPY (1, signum, csig);
199      if (csig < 0 || csig > NSIG)
200        SCM_OUT_OF_RANGE (1, signum);
201  #if defined(HAVE_SIGACTION)  #if defined(HAVE_SIGACTION)
202  #if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)  #if defined(SA_RESTART) && defined(HAVE_RESTARTABLE_SYSCALLS)
203    /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS    /* don't allow SA_RESTART to be omitted if HAVE_RESTARTABLE_SYSCALLS
# Line 211  SCM_DEFINE (scm_sigaction, "sigaction", Line 213  SCM_DEFINE (scm_sigaction, "sigaction",
213        action.sa_flags |= SCM_INUM (flags);        action.sa_flags |= SCM_INUM (flags);
214      }      }
215    sigemptyset (&action.sa_mask);    sigemptyset (&action.sa_mask);
216      if (SCM_UNBNDP (thread))
217        thread = scm_current_thread ();
218      else
219        SCM_VALIDATE_THREAD (4, thread);
220  #endif  #endif
221    SCM_DEFER_INTS;    SCM_DEFER_INTS;
222    old_handler = SCM_VELTS(*signal_handlers)[csig];    old_handler = SCM_VECTOR_REF(*signal_handlers, csig);
223    if (SCM_UNBNDP (handler))    if (SCM_UNBNDP (handler))
224      query_only = 1;      query_only = 1;
225    else if (SCM_EQ_P (scm_integer_p (handler), SCM_BOOL_T))    else if (SCM_EQ_P (scm_integer_p (handler), SCM_BOOL_T))
# Line 267  SCM_DEFINE (scm_sigaction, "sigaction", Line 273  SCM_DEFINE (scm_sigaction, "sigaction",
273        if (orig_handlers[csig] == SIG_ERR)        if (orig_handlers[csig] == SIG_ERR)
274          save_handler = 1;          save_handler = 1;
275  #endif  #endif
276          handler = close_1 (handler, signum);
277        SCM_VECTOR_SET (*signal_handlers, csig, handler);        SCM_VECTOR_SET (*signal_handlers, csig, handler);
278          SCM_VECTOR_SET (signal_handler_cells, csig,
279                          scm_cons (handler, SCM_EOL));
280          SCM_VECTOR_SET (signal_handler_threads, csig, thread);
281      }      }
282    
283    /* XXX - Silently ignore setting handlers for `program error signals'    /* XXX - Silently ignore setting handlers for `program error signals'
# Line 555  SCM_DEFINE (scm_raise, "raise", 1, 0, 0, Line 565  SCM_DEFINE (scm_raise, "raise", 1, 0, 0,
565  void  void
566  scm_init_scmsigs ()  scm_init_scmsigs ()
567  {  {
   SCM thunk;  
568    int i;    int i;
569    
570    signal_handlers =    signal_handlers =
571      SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",      SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
572                                    scm_c_make_vector (NSIG, SCM_BOOL_F)));                                    scm_c_make_vector (NSIG, SCM_BOOL_F)));
573    /* XXX - use scm_c_make_gsubr here instead of `define'? */    signal_handler_cells =
574    thunk = scm_c_define_gsubr ("%deliver-signals", 0, 0, 0,      scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
575                                sys_deliver_signals);    signal_handler_threads =
576    signal_async = scm_system_async (thunk);      scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
577    
578    for (i = 0; i < NSIG; i++)    for (i = 0; i < NSIG; i++)
579      {      {
       got_signal[i] = 0;  
580  #ifdef HAVE_SIGACTION  #ifdef HAVE_SIGACTION
581        orig_handlers[i].sa_handler = SIG_ERR;        orig_handlers[i].sa_handler = SIG_ERR;
582    

Legend:
Removed from v.1.69  
changed lines
  Added in v.1.70

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26