netlib.narod.ru< Назад | Оглавление | Далее >

arch/i386/kernel/signal.c

 2744 /*
 2745  *  linux/arch/i386/kernel/signal.c
 2746  *
 2747  *  Copyright (C) 1991, 1992  Linus Torvalds
 2748  *  1997-11-28 Modified for POSIX.1b signals by Richard
 2749  *  Henderson */
 2750 
 2751 #include <linux/config.h>
 2752 
 2753 #include <linux/sched.h>
 2754 #include <linux/mm.h>
 2755 #include <linux/smp.h>
 2756 #include <linux/smp_lock.h>
 2757 #include <linux/kernel.h>
 2758 #include <linux/signal.h>
 2759 #include <linux/errno.h>
 2760 #include <linux/wait.h>
 2761 #include <linux/ptrace.h>
 2762 #include <linux/unistd.h>
 2763 #include <linux/stddef.h>
 2764 #include <asm/ucontext.h>
 2765 #include <asm/uaccess.h>
 2766 
 2767 #define DEBUG_SIG 0
 2768 
 2769 #define _BLOCKABLE (~(sigmask(SIGKILL)|sigmask(SIGSTOP)))
 2770 
 2771 asmlinkage int sys_wait4(pid_t pid,
 2772                          unsigned long *stat_addr,
 2773                          int options, unsigned long *ru);
 2774 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs,
 2775                                   sigset_t *oldset));
 2776 
 2777 /* Atomically swap in the new signal mask, and wait for a
 2778  * signal.  */
 2779 asmlinkage int
 2780 sys_sigsuspend(int history0, int history1,
 2781                old_sigset_t mask)
 2782 {
 2783   struct pt_regs * regs = (struct pt_regs *) &history0;
 2784   sigset_t saveset;
 2785 
 2786   mask &= _BLOCKABLE;
 2787   spin_lock_irq(&current->sigmask_lock);
 2788   saveset = current->blocked;
 2789   siginitset(&current->blocked, mask);
 2790   recalc_sigpending(current);
 2791   spin_unlock_irq(&current->sigmask_lock);
 2792 
 2793   regs->eax = -EINTR;
 2794   while (1) {
 2795     current->state = TASK_INTERRUPTIBLE;
 2796     schedule();
 2797     if (do_signal(regs, &saveset))
 2798       return -EINTR;
 2799   }
 2800 }
 2801 
 2802 asmlinkage int
 2803 sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
 2804 {
 2805   struct pt_regs * regs = (struct pt_regs *) &unewset;
 2806   sigset_t saveset, newset;
 2807 
 2808   /* XXX: Don't preclude handling different sized
 2809    * sigset_t's.  */
 2810   if (sigsetsize != sizeof(sigset_t))
 2811     return -EINVAL;
 2812 
 2813   if (copy_from_user(&newset, unewset, sizeof(newset)))
 2814     return -EFAULT;
 2815   sigdelsetmask(&newset, ~_BLOCKABLE);
 2816 
 2817   spin_lock_irq(&current->sigmask_lock);
 2818   saveset = current->blocked;
 2819   current->blocked = newset;
 2820   recalc_sigpending(current);
 2821   spin_unlock_irq(&current->sigmask_lock);
 2822 
 2823   regs->eax = -EINTR;
 2824   while (1) {
 2825     current->state = TASK_INTERRUPTIBLE;
 2826     schedule();
 2827     if (do_signal(regs, &saveset))
 2828       return -EINTR;
 2829   }
 2830 }
 2831 
 2832 asmlinkage int
 2833 sys_sigaction(int sig, const struct old_sigaction *act,
 2834         struct old_sigaction *oact)
 2835 {
 2836   struct k_sigaction new_ka, old_ka;
 2837   int ret;
 2838 
 2839   if (act) {
 2840     old_sigset_t mask;
 2841     if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
 2842         __get_user(new_ka.sa.sa_handler,
 2843                    &act->sa_handler) ||
 2844         __get_user(new_ka.sa.sa_restorer,
 2845                    &act->sa_restorer))
 2846       return -EFAULT;
 2847     __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 2848     __get_user(mask, &act->sa_mask);
 2849     siginitset(&new_ka.sa.sa_mask, mask);
 2850   }
 2851 
 2852   ret = do_sigaction(sig, act ? &new_ka : NULL,
 2853                          oact ? &old_ka : NULL);
 2854 
 2855   if (!ret && oact) {
 2856     if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
 2857         __put_user(old_ka.sa.sa_handler,
 2858                    &oact->sa_handler) ||
 2859         __put_user(old_ka.sa.sa_restorer,
 2860                    &oact->sa_restorer))
 2861       return -EFAULT;
 2862     __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 2863     __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 2864   }
 2865 
 2866   return ret;
 2867 }
 2868 
 2869 asmlinkage int
 2870 sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 2871 {
 2872   struct pt_regs *regs = (struct pt_regs *) &uss;
 2873   return do_sigaltstack(uss, uoss, regs->esp);
 2874 }
 2875 
 2876 
 2877 /* Do a signal return; undo the signal stack.  */
 2878 
 2879 struct sigframe
 2880 {
 2881   char *pretcode;
 2882   int sig;
 2883   struct sigcontext sc;
 2884   struct _fpstate fpstate;
 2885   unsigned long extramask[_NSIG_WORDS-1];
 2886   char retcode[8];
 2887 };
 2888 
 2889 struct rt_sigframe
 2890 {
 2891   char *pretcode;
 2892   int sig;
 2893   struct siginfo *pinfo;
 2894   void *puc;
 2895   struct siginfo info;
 2896   struct ucontext uc;
 2897   struct _fpstate fpstate;
 2898   char retcode[8];
 2899 };
 2900 
 2901 
 2902 static inline int restore_i387_hard(struct _fpstate *buf)
 2903 {
 2904   struct task_struct *tsk = current;
 2905   clear_fpu(tsk);
 2906   return __copy_from_user(&tsk->tss.i387.hard, buf,
 2907                           sizeof(*buf));
 2908 }
 2909 
 2910 static inline int restore_i387(struct _fpstate *buf)
 2911 {
 2912   int err;
 2913 #ifndef CONFIG_MATH_EMULATION
 2914   err = restore_i387_hard(buf);
 2915 #else
 2916   if (boot_cpu_data.hard_math)
 2917     err = restore_i387_hard(buf);
 2918   else
 2919     err = restore_i387_soft(&current->tss.i387.soft,buf);
 2920 #endif
 2921   current->used_math = 1;
 2922   return err;
 2923 }
 2924 
 2925 static int
 2926 restore_sigcontext(struct pt_regs *regs,
 2927                    struct sigcontext *sc, int *peax)
 2928 {
 2929   unsigned int err = 0;
 2930 
 2931 #define COPY(x)        err |= __get_user(regs->x, &sc->x)
 2932 
 2933 #define COPY_SEG(seg)                                   \
 2934   { unsigned short tmp;                                 \
 2935     err |= __get_user(tmp, &sc->seg);                   \
 2936     regs->x##seg = tmp; }
 2937 
 2938 #define COPY_SEG_STRICT(seg)                            \
 2939   { unsigned short tmp;                                 \
 2940     err |= __get_user(tmp, &sc->seg);                   \
 2941     regs->x##seg = tmp|3; }
 2942 
 2943 #define GET_SEG(seg)                                    \
 2944   { unsigned short tmp;                                 \
 2945     err |= __get_user(tmp, &sc->seg);                   \
 2946     loadsegment(seg,tmp); }
 2947 
 2948   GET_SEG(gs);
 2949   GET_SEG(fs);
 2950   COPY_SEG(es);
 2951   COPY_SEG(ds);
 2952   COPY(edi);
 2953   COPY(esi);
 2954   COPY(ebp);
 2955   COPY(esp);
 2956   COPY(ebx);
 2957   COPY(edx);
 2958   COPY(ecx);
 2959   COPY(eip);
 2960   COPY_SEG_STRICT(cs);
 2961   COPY_SEG_STRICT(ss);
 2962 
 2963   {
 2964     unsigned int tmpflags;
 2965     err |= __get_user(tmpflags, &sc->eflags);
 2966     regs->eflags = (regs->eflags & ~0x40DD5) |
 2967                    (tmpflags & 0x40DD5);
 2968     regs->orig_eax = -1;     /* disable syscall checks */
 2969   }
 2970 
 2971   {
 2972     struct _fpstate * buf;
 2973     err |= __get_user(buf, &sc->fpstate);
 2974     if (buf) {
 2975       if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
 2976         goto badframe;
 2977       err |= restore_i387(buf);
 2978     }
 2979   }
 2980 
 2981   err |= __get_user(*peax, &sc->eax);
 2982   return err;
 2983 
 2984 badframe:
 2985   return 1;
 2986 }
 2987 
 2988 asmlinkage int sys_sigreturn(unsigned long __unused)
 2989 {
 2990   struct pt_regs *regs = (struct pt_regs *) &__unused;
 2991   struct sigframe *frame =
 2992     (struct sigframe *)(regs->esp - 8);
 2993   sigset_t set;
 2994   int eax;
 2995 
 2996   if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 2997     goto badframe;
 2998   if (__get_user(set.sig[0], &frame->sc.oldmask)
 2999       || (_NSIG_WORDS > 1
 3000     && __copy_from_user(&set.sig[1], &frame->extramask,
 3001             sizeof(frame->extramask))))
 3002     goto badframe;
 3003 
 3004   sigdelsetmask(&set, ~_BLOCKABLE);
 3005   spin_lock_irq(&current->sigmask_lock);
 3006   current->blocked = set;
 3007   recalc_sigpending(current);
 3008   spin_unlock_irq(&current->sigmask_lock);
 3009 
 3010   if (restore_sigcontext(regs, &frame->sc, &eax))
 3011     goto badframe;
 3012   return eax;
 3013 
 3014 badframe:
 3015   force_sig(SIGSEGV, current);
 3016   return 0;
 3017 }
 3018 
 3019 asmlinkage int sys_rt_sigreturn(unsigned long __unused)
 3020 {
 3021   struct pt_regs *regs = (struct pt_regs *) &__unused;
 3022   struct rt_sigframe *frame =
 3023     (struct rt_sigframe *)(regs->esp - 4);
 3024   sigset_t set;
 3025   stack_t st;
 3026   int eax;
 3027 
 3028   if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 3029     goto badframe;
 3030   if (__copy_from_user(&set, &frame->uc.uc_sigmask,
 3031                        sizeof(set)))
 3032     goto badframe;
 3033 
 3034   sigdelsetmask(&set, ~_BLOCKABLE);
 3035   spin_lock_irq(&current->sigmask_lock);
 3036   current->blocked = set;
 3037   recalc_sigpending(current);
 3038   spin_unlock_irq(&current->sigmask_lock);
 3039 
 3040   if (restore_sigcontext(regs, &frame->uc.uc_mcontext,
 3041                          &eax))
 3042     goto badframe;
 3043 
 3044   if (__copy_from_user(&st, &frame->uc.uc_stack,
 3045                        sizeof(st)))
 3046     goto badframe;
 3047   /* It is more difficult to avoid calling this function
 3048    * than to call it and ignore errors.  */
 3049   do_sigaltstack(&st, NULL, regs->esp);
 3050 
 3051   return eax;
 3052 
 3053 badframe:
 3054   force_sig(SIGSEGV, current);
 3055   return 0;
 3056 }
 3057 
 3058 /* Set up a signal frame.  */
 3059 
 3060 static inline int save_i387_hard(struct _fpstate * buf)
 3061 {
 3062   struct task_struct *tsk = current;
 3063 
 3064   unlazy_fpu(tsk);
 3065   tsk->tss.i387.hard.status = tsk->tss.i387.hard.swd;
 3066   if (__copy_to_user(buf, &tsk->tss.i387.hard,
 3067                      sizeof(*buf)))
 3068     return -1;
 3069   return 1;
 3070 }
 3071 
 3072 static int save_i387(struct _fpstate *buf)
 3073 {
 3074   if (!current->used_math)
 3075     return 0;
 3076 
 3077   /* This will cause a "finit" to be triggered by the
 3078    * next attempted FPU operation by the 'current'
 3079    * process.  */
 3080   current->used_math = 0;
 3081 
 3082 #ifndef CONFIG_MATH_EMULATION
 3083   return save_i387_hard(buf);
 3084 #else
 3085   return boot_cpu_data.hard_math ? save_i387_hard(buf)
 3086     : save_i387_soft(&current->tss.i387.soft, buf);
 3087 #endif
 3088 }
 3089 
 3090 static int
 3091 setup_sigcontext(struct sigcontext *sc,
 3092                  struct _fpstate *fpstate,
 3093                  struct pt_regs *regs,unsigned long mask)
 3094 {
 3095   int tmp, err = 0;
 3096 
 3097   tmp = 0;
 3098   __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp));
 3099   err |= __put_user(tmp, (unsigned int *)&sc->gs);
 3100   __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp));
 3101   err |= __put_user(tmp, (unsigned int *)&sc->fs);
 3102 
 3103   err |= __put_user(regs->xes, (unsigned int *)&sc->es);
 3104   err |= __put_user(regs->xds, (unsigned int *)&sc->ds);
 3105   err |= __put_user(regs->edi, &sc->edi);
 3106   err |= __put_user(regs->esi, &sc->esi);
 3107   err |= __put_user(regs->ebp, &sc->ebp);
 3108   err |= __put_user(regs->esp, &sc->esp);
 3109   err |= __put_user(regs->ebx, &sc->ebx);
 3110   err |= __put_user(regs->edx, &sc->edx);
 3111   err |= __put_user(regs->ecx, &sc->ecx);
 3112   err |= __put_user(regs->eax, &sc->eax);
 3113   err |= __put_user(current->tss.trap_no, &sc->trapno);
 3114   err |= __put_user(current->tss.error_code, &sc->err);
 3115   err |= __put_user(regs->eip, &sc->eip);
 3116   err |= __put_user(regs->xcs, (unsigned int *)&sc->cs);
 3117   err |= __put_user(regs->eflags, &sc->eflags);
 3118   err |= __put_user(regs->esp, &sc->esp_at_signal);
 3119   err |= __put_user(regs->xss, (unsigned int *)&sc->ss);
 3120 
 3121   tmp = save_i387(fpstate);
 3122   if (tmp < 0)
 3123     err = 1;
 3124   else
 3125     err |= __put_user(tmp ? fpstate : NULL,&sc->fpstate);
 3126 
 3127   /* non-iBCS2 extensions.. */
 3128   err |= __put_user(mask, &sc->oldmask);
 3129   err |= __put_user(current->tss.cr2, &sc->cr2);
 3130 
 3131   return err;
 3132 }
 3133 
 3134 /* Determine which stack to use..  */
 3135 static inline void *
 3136 get_sigframe(struct k_sigaction *ka,
 3137              struct pt_regs * regs, size_t frame_size)
 3138 {
 3139   unsigned long esp;
 3140 
 3141   /* Default to using normal stack */
 3142   esp = regs->esp;
 3143 
 3144   /* This is the X/Open sanctioned signal stack
 3145    * switching.  */
 3146   if (ka->sa.sa_flags & SA_ONSTACK) {
 3147     if (! on_sig_stack(esp))
 3148       esp = current->sas_ss_sp + current->sas_ss_size;
 3149   }
 3150 
 3151   /* This is the legacy signal stack switching. */
 3152   else if ((regs->xss & 0xffff) != __USER_DS &&
 3153      !(ka->sa.sa_flags & SA_RESTORER) &&
 3154      ka->sa.sa_restorer) {
 3155     esp = (unsigned long) ka->sa.sa_restorer;
 3156   }
 3157 
 3158   return (void *)((esp - frame_size) & -8ul);
 3159 }
 3160 
 3161 static void setup_frame(int sig, struct k_sigaction *ka,
 3162       sigset_t *set, struct pt_regs * regs)
 3163 {
 3164   struct sigframe *frame;
 3165   int err = 0;
 3166 
 3167   frame = get_sigframe(ka, regs, sizeof(*frame));
 3168 
 3169   if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 3170     goto give_sigsegv;
 3171 
 3172   err |= __put_user((current->exec_domain
 3173          && current->exec_domain->signal_invmap
 3174          && sig < 32
 3175          ? current->exec_domain->signal_invmap[sig]
 3176          : sig),
 3177         &frame->sig);
 3178 
 3179   err |= setup_sigcontext(&frame->sc, &frame->fpstate,
 3180                           regs, set->sig[0]);
 3181 
 3182   if (_NSIG_WORDS > 1) {
 3183     err |= __copy_to_user(frame->extramask, &set->sig[1],
 3184               sizeof(frame->extramask));
 3185   }
 3186 
 3187   /* Set up to return from userspace.  If provided, use a
 3188    * stub already in userspace.  */
 3189   if (ka->sa.sa_flags & SA_RESTORER) {
 3190     err |= __put_user(ka->sa.sa_restorer,
 3191                       &frame->pretcode);
 3192   } else {
 3193     err |= __put_user(frame->retcode, &frame->pretcode);
 3194     /* This is popl %eax ; movl $,%eax ; int $0x80 */
 3195     err |= __put_user(0xb858,
 3196                       (short *)(frame->retcode+0));
 3197     err |= __put_user(__NR_sigreturn,
 3198                       (int *)(frame->retcode+2));
 3199     err |= __put_user(0x80cd,
 3200                       (short *)(frame->retcode+6));
 3201   }
 3202 
 3203   if (err)
 3204     goto give_sigsegv;
 3205 
 3206   /* Set up registers for signal handler */
 3207   regs->esp = (unsigned long) frame;
 3208   regs->eip = (unsigned long) ka->sa.sa_handler;
 3209 
 3210   set_fs(USER_DS);
 3211   regs->xds = __USER_DS;
 3212   regs->xes = __USER_DS;
 3213   regs->xss = __USER_DS;
 3214   regs->xcs = __USER_CS;
 3215   regs->eflags &= ~TF_MASK;
 3216 
 3217 #if DEBUG_SIG
 3218   printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
 3219          current->comm, current->pid, frame, regs->eip,
 3220          frame->pretcode);
 3221 #endif
 3222 
 3223   return;
 3224 
 3225 give_sigsegv:
 3226   if (sig == SIGSEGV)
 3227     ka->sa.sa_handler = SIG_DFL;
 3228   force_sig(SIGSEGV, current);
 3229 }
 3230 
 3231 static void setup_rt_frame(int sig,
 3232   struct k_sigaction *ka, siginfo_t *info,
 3233   sigset_t *set, struct pt_regs * regs)
 3234 {
 3235   struct rt_sigframe *frame;
 3236   int err = 0;
 3237 
 3238   frame = get_sigframe(ka, regs, sizeof(*frame));
 3239 
 3240   if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 3241     goto give_sigsegv;
 3242 
 3243   err |= __put_user((current->exec_domain
 3244          && current->exec_domain->signal_invmap
 3245          && sig < 32
 3246          ? current->exec_domain->signal_invmap[sig]
 3247          : sig),
 3248         &frame->sig);
 3249   err |= __put_user(&frame->info, &frame->pinfo);
 3250   err |= __put_user(&frame->uc, &frame->puc);
 3251   err |= __copy_to_user(&frame->info,info,sizeof(*info));
 3252 
 3253   /* Create the ucontext.  */
 3254   err |= __put_user(0, &frame->uc.uc_flags);
 3255   err |= __put_user(0, &frame->uc.uc_link);
 3256   err |= __put_user(current->sas_ss_sp,
 3257                     &frame->uc.uc_stack.ss_sp);
 3258   err |= __put_user(sas_ss_flags(regs->esp),
 3259                     &frame->uc.uc_stack.ss_flags);
 3260   err |= __put_user(current->sas_ss_size,
 3261                     &frame->uc.uc_stack.ss_size);
 3262   err |= setup_sigcontext(&frame->uc.uc_mcontext,
 3263                           &frame->fpstate,
 3264                           regs, set->sig[0]);
 3265   err |= __copy_to_user(&frame->uc.uc_sigmask, set,
 3266                         sizeof(*set));
 3267 
 3268   /* Set up to return from userspace.  If provided, use a
 3269    * stub already in userspace.  */
 3270   if (ka->sa.sa_flags & SA_RESTORER) {
 3271     err |= __put_user(ka->sa.sa_restorer,
 3272                       &frame->pretcode);
 3273   } else {
 3274     err |= __put_user(frame->retcode, &frame->pretcode);
 3275     /* This is movl $,%eax ; int $0x80 */
 3276     err |= __put_user(0xb8, (char *)(frame->retcode+0));
 3277     err |= __put_user(__NR_rt_sigreturn,
 3278                       (int *)(frame->retcode+1));
 3279     err |= __put_user(0x80cd,
 3280                       (short *)(frame->retcode+5));
 3281   }
 3282 
 3283   if (err)
 3284     goto give_sigsegv;
 3285 
 3286   /* Set up registers for signal handler */
 3287   regs->esp = (unsigned long) frame;
 3288   regs->eip = (unsigned long) ka->sa.sa_handler;
 3289 
 3290   set_fs(USER_DS);
 3291   regs->xds = __USER_DS;
 3292   regs->xes = __USER_DS;
 3293   regs->xss = __USER_DS;
 3294   regs->xcs = __USER_CS;
 3295   regs->eflags &= ~TF_MASK;
 3296 
 3297 #if DEBUG_SIG
 3298   printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
 3299          current->comm, current->pid, frame, regs->eip,
 3300          frame->pretcode);
 3301 #endif
 3302 
 3303   return;
 3304 
 3305 give_sigsegv:
 3306   if (sig == SIGSEGV)
 3307     ka->sa.sa_handler = SIG_DFL;
 3308   force_sig(SIGSEGV, current);
 3309 }
 3310 
 3311 /* OK, we're invoking a handler */
 3312 
 3313 static void
 Комментарий
 3314 handle_signal(unsigned long sig, struct k_sigaction *ka,
 3315 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 3316 {
 3317   /* Are we from a system call? */
 3318   if (regs->orig_eax >= 0) {
 3319     /* If so, check system call restarting.. */
 3320     switch (regs->eax) {
 3321       case -ERESTARTNOHAND:
 3322         regs->eax = -EINTR;
 3323         break;
 3324 
 3325       case -ERESTARTSYS:
 3326         if (!(ka->sa.sa_flags & SA_RESTART)) {
 3327           regs->eax = -EINTR;
 3328           break;
 3329         }
 3330       /* fallthrough */
 3331       case -ERESTARTNOINTR:
 3332         regs->eax = regs->orig_eax;
 3333         regs->eip -= 2;
 3334     }
 3335   }
 3336 
 3337   /* Set up the stack frame */
 3338   if (ka->sa.sa_flags & SA_SIGINFO)
 3339     setup_rt_frame(sig, ka, info, oldset, regs);
 3340   else
 3341     setup_frame(sig, ka, oldset, regs);
 3342 
 3343   if (ka->sa.sa_flags & SA_ONESHOT)
 3344     ka->sa.sa_handler = SIG_DFL;
 3345 
 3346   if (!(ka->sa.sa_flags & SA_NODEFER)) {
 3347     spin_lock_irq(&current->sigmask_lock);
 3348     sigorsets(&current->blocked,&current->blocked,
 3349               &ka->sa.sa_mask);
 3350     sigaddset(&current->blocked,sig);
 3351     recalc_sigpending(current);
 3352     spin_unlock_irq(&current->sigmask_lock);
 3353   }
 3354 }
 3355 
 3356 /* Note that 'init' is a special process: it doesn't get
 3357  * signals it doesn't want to handle. Thus you cannot
 3358  * kill init even with a SIGKILL even by mistake.
 3359  *
 3360  * Note that we go through the signals twice: once to
 3361  * check the signals that the kernel can handle, and then
 3362  * we build all the user-level signal handling
 3363  * stack-frames in one go after that.  */
 Комментарий
 3364 int do_signal(struct pt_regs *regs, sigset_t *oldset)
 3365 {
 3366   siginfo_t info;
 3367   struct k_sigaction *ka;
 3368 
 3369   /* We want the common case to go fast, which is why we
 3370    * may in certain cases get here from kernel mode. Just
 3371    * return without doing anything if so.  */
 3372   if ((regs->xcs & 3) != 3)
 3373     return 1;
 3374 
 3375   if (!oldset)
 3376     oldset = &current->blocked;
 3377 
 3378   for (;;) {
 3379     unsigned long signr;
 3380 
 3381     spin_lock_irq(&current->sigmask_lock);
 3382     signr = dequeue_signal(&current->blocked, &info);
 3383     spin_unlock_irq(&current->sigmask_lock);
 3384 
 3385     if (!signr)
 3386       break;
 3387 
 3388     if ((current->flags & PF_PTRACED) &&
 3389         signr != SIGKILL) {
 3390       /* Let the debugger run.  */
 3391       current->exit_code = signr;
 3392       current->state = TASK_STOPPED;
 3393       notify_parent(current, SIGCHLD);
 3394       schedule();
 3395 
 3396       /* We're back.  Did the debugger cancel the sig? */
 3397       if (!(signr = current->exit_code))
 3398         continue;
 3399       current->exit_code = 0;
 3400 
 3401       /* The debugger continued.  Ignore SIGSTOP.  */
 3402       if (signr == SIGSTOP)
 3403         continue;
 3404 
 3405       /* Update the siginfo structure.  Is this good?  */
 3406       if (signr != info.si_signo) {
 3407         info.si_signo = signr;
 3408         info.si_errno = 0;
 3409         info.si_code = SI_USER;
 3410         info.si_pid = current->p_pptr->pid;
 3411         info.si_uid = current->p_pptr->uid;
 3412       }
 3413 
 3414       /* If (new) signal is now blocked, requeue it.  */
 3415       if (sigismember(&current->blocked, signr)) {
 3416         send_sig_info(signr, &info, current);
 3417         continue;
 3418       }
 3419     }
 3420 
 3421     ka = &current->sig->action[signr-1];
 3422     if (ka->sa.sa_handler == SIG_IGN) {
 3423       if (signr != SIGCHLD)
 3424         continue;
 3425       /* Check for SIGCHLD: it's special.  */
 3426       while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
 3427         /* nothing */;
 3428       continue;
 3429     }
 3430 
 3431     if (ka->sa.sa_handler == SIG_DFL) {
 3432       int exit_code = signr;
 3433 
 3434       /* Init gets no signals it doesn't want.  */
 3435       if (current->pid == 1)
 3436         continue;
 3437 
 3438       switch (signr) {
 3439       case SIGCONT: case SIGCHLD: case SIGWINCH:
 3440         continue;
 3441 
 3442       case SIGTSTP: case SIGTTIN: case SIGTTOU:
 3443         if (is_orphaned_pgrp(current->pgrp))
 3444           continue;
 3445         /* FALLTHRU */
 3446 
 3447       case SIGSTOP:
 3448         current->state = TASK_STOPPED;
 3449         current->exit_code = signr;
 3450         if (!(current->p_pptr->sig->action[SIGCHLD-1].
 3451                              sa.sa_flags & SA_NOCLDSTOP))
 3452           notify_parent(current, SIGCHLD);
 3453         schedule();
 3454         continue;
 3455 
 Комментарий
 3456       case SIGQUIT: case SIGILL: case SIGTRAP:
 3457       case SIGABRT: case SIGFPE: case SIGSEGV:
 3458         lock_kernel();
 3459         if (current->binfmt
 3460             && current->binfmt->core_dump
 3461             && current->binfmt->core_dump(signr, regs))
 3462           exit_code |= 0x80;
 3463         unlock_kernel();
 3464         /* FALLTHRU */
 3465 
 3466       default:
 3467         lock_kernel();
 3468         sigaddset(&current->signal, signr);
 3469         current->flags |= PF_SIGNALED;
 3470         do_exit(exit_code);
 3471         /* NOTREACHED */
 3472       }
 3473     }
 3474 
 3475     /* Whee!  Actually deliver the signal.  */
 3476     handle_signal(signr, ka, &info, oldset, regs);
 3477     return 1;
 3478   }
 3479 
 3480   /* Did we come from a system call? */
 3481   if (regs->orig_eax >= 0) {
 3482     /* Restart the system call - no handlers present */
 3483     if (regs->eax == -ERESTARTNOHAND ||
 3484         regs->eax == -ERESTARTSYS ||
 3485         regs->eax == -ERESTARTNOINTR) {
 3486       regs->eax = regs->orig_eax;
 3487       regs->eip -= 2;
 3488     }
 3489   }
 3490   return 0;
 3491 }

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz