zoukankan      html  css  js  c++  java
  • 信号对ERESTARTSYS的处理

    一、问题

    在看nanosleep的时候,看到这个函数返回的错误码是-ERESTART_RESTARTBLOCK,所以就比较好奇的看了这个地方的代码,然后看到是在do_signal和handle_signal函数中判断了这些错误码的意义。然后就看一下它们具体的意义。

    二、信号的发送

    sys_kill(int pid, int sig)---》》》kill_something_info---》》》kill_pid_info---》》》group_send_sig_info----》》》__group_send_sig_info

     /* Short-circuit ignored signals.  */
     if (sig_ignored(p, sig))
      return ret;

     if (LEGACY_QUEUE(&p->signal->shared_pending, sig))
      /* This is a non-RT signal and we already have one queued.  */
      return ret;
    这里的内核可忽略信号有

    static int sig_ignored(struct task_struct *t, int sig)
    {
     void __user * handler;

     /*
      * Tracers always want to know about signals..
      */
     if (t->ptrace & PT_PTRACED)
      return 0;

     /*
      * Blocked signals are never ignored, since the
      * signal handler may change by the time it is
      * unblocked.
      */
     if (sigismember(&t->blocked, sig))
      return 0;

     /* Is it explicitly or implicitly ignored? */
     handler = t->sighand->action[sig-1].sa.sa_handler;
     return   handler == SIG_IGN ||
      (handler == SIG_DFL && sig_kernel_ignore(sig));
    }

    也就是

    #define sig_kernel_ignore(sig)
      (((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_IGNORE_MASK))

    这些信号如果没有安装信号处理函数,那么这个地方发送信号也不会将线程唤醒。

    但是我们现在假设是其它的信号。

    三、信号的执行

    static void fastcall do_signal(struct pt_regs *regs)---》》》get_signal_to_deliver

      signr = dequeue_signal(current, mask, info);
    ……

     ka = &current->sighand->action[signr-1];
      if (ka->sa.sa_handler == SIG_IGN) /* Do nothing.  */
       continue;
      if (ka->sa.sa_handler != SIG_DFL) {
       /* Run the handler.  */
       *return_ka = *ka;

       if (ka->sa.sa_flags & SA_ONESHOT)
        ka->sa.sa_handler = SIG_DFL;

       break; /* will return non-zero "signr" value */
      }

      /*
       * Now we are doing the default action for this signal.
       */
      if (sig_kernel_ignore(signr)) /* Default is nothing. */ 走到这里,说明这个信号是SIG_DFL,否则将会在上面直接退出
       continue;

    假设对于其它的不能忽略信号,例如SIGPIPE信号,此时就会执行到上面的SIG_IGN的时候进入continue,从而这个信号被消耗掉,从而执行到下面的返回,最终这个函数返回的信号值可能为零。

    signr = get_signal_to_deliver(&info, &ka, regs, NULL);
     if (signr > 0
    ) {
      /* Reenable any watchpoints before delivering the
       * signal to user space. The processor register will
       * have been cleared if the watchpoint triggered
       * inside the kernel.
       */
      if (unlikely(current->thread.debugreg[7]))
       set_debugreg(current->thread.debugreg[7], 7);

      /* Whee!  Actually deliver the signal.  */
      if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
       /* a signal was successfully delivered; the saved
        * sigmask will have been stored in the signal frame,
        * and will be restored by sigreturn, so we can simply
        * clear the TIF_RESTORE_SIGMASK flag */
       if (test_thread_flag(TIF_RESTORE_SIGMASK))
        clear_thread_flag(TIF_RESTORE_SIGMASK);
      }

      return;
     }

     /* Did we come from a system call? */
     if (regs->orig_eax >= 0) { 只有返回值为零,才会执行下面的函数,说明信号被忽略了或者说是缺省处理
      /* Restart the system call - no handlers present */
      switch (regs->eax) {
      case -ERESTARTNOHAND:
      case -ERESTARTSYS:
      case -ERESTARTNOINTR:
       regs->eax = regs->orig_eax;
       regs->eip -= 2;
       break;

      case -ERESTART_RESTARTBLOCK:
       regs->eax = __NR_restart_syscall;
       regs->eip -= 2;
       break;
      }
     }
    对于未忽略的信号,处理流程为


     /* Are we from a system call? */
     if (regs->orig_eax >= 0) {
      /* If so, check system call restarting.. */
      switch (regs->eax) {
              case -ERESTART_RESTARTBLOCK:
       case -ERESTARTNOHAND:
        regs->eax = -EINTR;
        break;

       case -ERESTARTSYS:
        if (!(ka->sa.sa_flags & SA_RESTART)) {
         regs->eax = -EINTR;
         break;
        }
       /* fallthrough */
       case -ERESTARTNOINTR:
        regs->eax = regs->orig_eax;
        regs->eip -= 2
    只有这种情况下一定会处理信号,其它的都没有保证。也就是说,只要安装了信号处理函数,那么很可能会都不会重新执行系统调用
      }
     }

  • 相关阅读:
    [Swift] Swift3.0--GCD
    [Android Pro] Swift 3.0多线程
    [MAC OS ] UserDefaults
    [MAC OS] NSOpenPanel 使用
    [ IOS ] iOS-控制器View的创建和生命周期
    [ IOS ] 视图控制对象ViewController的生命周期
    [Android Pro] AtomicInteger的用法
    [MAC OS] 常用工具
    [MAC OS] NSButton tag 获取
    [MAC OS] XCode中的Debug View Hierarchy功能
  • 原文地址:https://www.cnblogs.com/tsecer/p/10485729.html
Copyright © 2011-2022 走看看