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(¤t->sigmask_lock);
2788 saveset = current->blocked;
2789 siginitset(¤t->blocked, mask);
2790 recalc_sigpending(current);
2791 spin_unlock_irq(¤t->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(¤t->sigmask_lock);
2818 saveset = current->blocked;
2819 current->blocked = newset;
2820 recalc_sigpending(current);
2821 spin_unlock_irq(¤t->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(¤t->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(¤t->sigmask_lock);
3006 current->blocked = set;
3007 recalc_sigpending(current);
3008 spin_unlock_irq(¤t->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(¤t->sigmask_lock);
3036 current->blocked = set;
3037 recalc_sigpending(current);
3038 spin_unlock_irq(¤t->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(¤t->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(¤t->sigmask_lock);
3348 sigorsets(¤t->blocked,¤t->blocked,
3349 &ka->sa.sa_mask);
3350 sigaddset(¤t->blocked,sig);
3351 recalc_sigpending(current);
3352 spin_unlock_irq(¤t->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 = ¤t->blocked;
3377
3378 for (;;) {
3379 unsigned long signr;
3380
3381 spin_lock_irq(¤t->sigmask_lock);
3382 signr = dequeue_signal(¤t->blocked, &info);
3383 spin_unlock_irq(¤t->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(¤t->blocked, signr)) {
3416 send_sig_info(signr, &info, current);
3417 continue;
3418 }
3419 }
3420
3421 ka = ¤t->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(¤t->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 }
Сайт управляется системой
uCoz