(linenum→info "unix/slp.c:2238")

glibc/2.7/hurd/catch-signal.c

    1: /* Convenience function to catch expected signals during an operation.
    2:    Copyright (C) 1996 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <hurd/signal.h>
   21: #include <hurd/sigpreempt.h>
   22: #include <string.h>
   23: #include <assert.h>
   24: 
   25: error_t
   26: hurd_catch_signal (sigset_t sigset,
   27:                    unsigned long int first, unsigned long int last,
   28:                    error_t (*operate) (struct hurd_signal_preemptor *),
   29:                    sighandler_t handler)
   30: {
   31:   jmp_buf buf;
   32:   void throw (int signo, long int sigcode, struct sigcontext *scp)
   33:     { longjmp (buf, scp->sc_error ?: EGRATUITOUS); }
   34: 
   35:   struct hurd_signal_preemptor preemptor =
   36:     {
   37:       sigset, first, last,
   38:       NULL, handler == SIG_ERR ? (sighandler_t) &throw : handler,
   39:     };
   40: 
   41:   struct hurd_sigstate *const ss = _hurd_self_sigstate ();
   42:   error_t error;
   43: 
   44:   if (handler == SIG_ERR)
   45:     /* Not our handler; don't bother saving state.  */
   46:     error = 0;
   47:   else
   48:     /* This returns again with nonzero value when we preempt a signal.  */
   49:     error = setjmp (buf);
   50: 
   51:   if (error == 0)
   52:     {
   53:       /* Install a signal preemptor for the thread.  */
   54:       __spin_lock (&ss->lock);
   55:       preemptor.next = ss->preemptors;
   56:       ss->preemptors = &preemptor;
   57:       __spin_unlock (&ss->lock);
   58: 
   59:       /* Try the operation that might crash.  */
   60:       (*operate) (&preemptor);
   61:     }
   62: 
   63:   /* Either FUNCTION completed happily and ERROR is still zero, or it hit
   64:      an expected signal and `throw' made setjmp return the signal error
   65:      code in ERROR.  Now we can remove the preemptor and return.  */
   66: 
   67:   __spin_lock (&ss->lock);
   68:   assert (ss->preemptors == &preemptor);
   69:   ss->preemptors = preemptor.next;
   70:   __spin_unlock (&ss->lock);
   71: 
   72:   return error;
   73: }
   74: 
   75: 
   76: error_t
   77: hurd_safe_memset (void *dest, int byte, size_t nbytes)
   78: {
   79:   error_t operate (struct hurd_signal_preemptor *preemptor)
   80:     {
   81:       memset (dest, byte, nbytes);
   82:       return 0;
   83:     }
   84:   return hurd_catch_signal (sigmask (SIGBUS) | sigmask (SIGSEGV),
   85:                             (vm_address_t) dest, (vm_address_t) dest + nbytes,
   86:                             &operate, SIG_ERR);
   87: }
   88: 
   89: 
   90: error_t
   91: hurd_safe_copyout (void *dest, const void *src, size_t nbytes)
   92: {
   93:   error_t operate (struct hurd_signal_preemptor *preemptor)
   94:     {
   95:       memcpy (dest, src, nbytes);
   96:       return 0;
   97:     }
   98:   return hurd_catch_signal (sigmask (SIGBUS) | sigmask (SIGSEGV),
   99:                             (vm_address_t) dest, (vm_address_t) dest + nbytes,
  100:                             &operate, SIG_ERR);
  101: }
  102: 
  103: error_t
  104: hurd_safe_copyin (void *dest, const void *src, size_t nbytes)
  105: {
  106:   error_t operate (struct hurd_signal_preemptor *preemptor)
  107:     {
  108:       memcpy (dest, src, nbytes);
  109:       return 0;
  110:     }
  111:   return hurd_catch_signal (sigmask (SIGBUS) | sigmask (SIGSEGV),
  112:                             (vm_address_t) src, (vm_address_t) src + nbytes,
  113:                             &operate, SIG_ERR);
  114: }
  115: 
  116: error_t
  117: hurd_safe_memmove (void *dest, const void *src, size_t nbytes)
  118: {
  119:   jmp_buf buf;
  120:   void throw (int signo, long int sigcode, struct sigcontext *scp)
  121:     { longjmp (buf, scp->sc_error ?: EGRATUITOUS); }
  122: 
  123:   struct hurd_signal_preemptor src_preemptor =
  124:     {
  125:       sigmask (SIGBUS) | sigmask (SIGSEGV),
  126:       (vm_address_t) src, (vm_address_t) src + nbytes,
  127:       NULL, (sighandler_t) &throw,
  128:     };
  129:   struct hurd_signal_preemptor dest_preemptor =
  130:     {
  131:       sigmask (SIGBUS) | sigmask (SIGSEGV),
  132:       (vm_address_t) dest, (vm_address_t) dest + nbytes,
  133:       NULL, (sighandler_t) &throw,
  134:       &src_preemptor
  135:     };
  136: 
  137:   struct hurd_sigstate *const ss = _hurd_self_sigstate ();
  138:   error_t error;
  139: 
  140:   /* This returns again with nonzero value when we preempt a signal.  */
  141:   error = setjmp (buf);
  142: 
  143:   if (error == 0)
  144:     {
  145:       /* Install a signal preemptor for the thread.  */
  146:       __spin_lock (&ss->lock);
  147:       src_preemptor.next = ss->preemptors;
  148:       ss->preemptors = &dest_preemptor;
  149:       __spin_unlock (&ss->lock);
  150: 
  151:       /* Do the copy; it might fault.  */
  152:       memmove (dest, src, nbytes);
  153:     }
  154: 
  155:   /* Either memmove completed happily and ERROR is still zero, or it hit
  156:      an expected signal and `throw' made setjmp return the signal error
  157:      code in ERROR.  Now we can remove the preemptor and return.  */
  158: 
  159:   __spin_lock (&ss->lock);
  160:   assert (ss->preemptors == &dest_preemptor);
  161:   ss->preemptors = src_preemptor.next;
  162:   __spin_unlock (&ss->lock);
  163: 
  164:   return error;
  165: }
Syntax (Markdown)