zoukankan      html  css  js  c++  java
  • android init重启service(进程)

    在init进程的main函数中有调用sigchld_handler_init() 设置SIGCHLD signal。这里设置SIGCHLD的处理函数时,在sa_flags中有加SA_NOCLDSTOP flag,这个flag表示只有当子进程终止时父进程才接受这个signal,当子进程在暂停或者继续运行的状态时是不会收到这个signal的。

    void sigchld_handler_init() {
        // Create a signalling mechanism for SIGCHLD.
        int s[2];
        if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {
            PLOG(FATAL) << "socketpair failed in sigchld_handler_init";
        }
    
        signal_write_fd = s[0];
        signal_read_fd = s[1];
    
        // Write to signal_write_fd if we catch SIGCHLD.
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIGCHLD_handler;
        act.sa_flags = SA_NOCLDSTOP;
        sigaction(SIGCHLD, &act, 0);
    
        ReapAnyOutstandingChildren();
    
        register_epoll_handler(signal_read_fd, handle_signal);
    }
    

    1. 注册的SIGCHLD处理函数是SIGCHLD_handler。

    2. 调用register_epoll_handler()

    init.cpp

    void register_epoll_handler(int fd, void (*fn)()) {
        epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.ptr = reinterpret_cast<void*>(fn);
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
            PLOG(ERROR) << "epoll_ctl failed";
        }
    }
    

      

    1. 在子进程退出时,init进程会收到SIGCHLD signal,然后调用SIGCHLD_handler()进行处理。这个函数只是简单地调用write()

    2. 由于上面有进行write,所以在init的main函数中的epoll_wait()会返回,然后调用通过register_epoll_handler()注册的函数,即hand_signal()

            epoll_event ev;
            int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
            if (nr == -1) {
                PLOG(ERROR) << "epoll_wait failed";
            } else if (nr == 1) {
                ((void (*)()) ev.data.ptr)();
            }
    

      

    在hand_signal()中,首先调用read()将数据读出,然后会调用到ReapOneProcess()。在这个函数中,调用waitpid()等待子进程退出,waitpid()会拿到一个siginfo,这个siginfo中有退出的子进程的pid。

    然后根据这个pid从ServiceList中找到这个退出的子进程的Service对象;

    然后调用这个Service对象的Reap()。

    在Reap函数中,首先调用KillProcessGroup(SIGKILL)。这个函数会调到system/core/libprocessgroup/processgroup.cpp中的killProcessGroup()。这个调用的目的是kill掉退出的子进程的所有子进程。

    void Service::KillProcessGroup(int signal) {
        // If we've already seen a successful result from killProcessGroup*(), then we have removed
        // the cgroup already and calling these functions a second time will simply result in an error.
        // This is true regardless of which signal was sent.
        // These functions handle their own logging, so no additional logging is needed.
        if (!process_cgroup_empty_) {
            LOG(INFO) << "Sending signal " << signal << " to service '" << name_ << "' (pid " << pid_
                      << ") process group...";
            int r;
            if (signal == SIGTERM) {
                r = killProcessGroupOnce(uid_, pid_, signal);
            } else {
                r = killProcessGroup(uid_, pid_, signal);
            }
    
            if (r == 0) process_cgroup_empty_ = true;
        }
    }

    然后调用UnsetExec()将is_exec_service_running_设置为false并将SVC_EXEC flag清掉;

    然后会将flags_中的SVC_RESTARTING flag设置上;

    然后调用onrestart_.ExecuteAllCommands()

    void Service::Reap(const siginfo_t& siginfo) {
        if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
            KillProcessGroup(SIGKILL);
        }
    
        // Remove any descriptor resources we may have created.
        std::for_each(descriptors_.begin(), descriptors_.end(),
                      std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
    
        for (const auto& f : reap_callbacks_) {
            f(siginfo);
        }
    
        if (flags_ & SVC_EXEC) UnSetExec();
    
        if (flags_ & SVC_TEMPORARY) return;
    
        pid_ = 0;
        flags_ &= (~SVC_RUNNING);
        start_order_ = 0;
    
        // Oneshot processes go into the disabled state on exit,
        // except when manually restarted.
        if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
            flags_ |= SVC_DISABLED;
        }
    
        // Disabled and reset processes do not get restarted automatically.
        if (flags_ & (SVC_DISABLED | SVC_RESET))  {
            NotifyStateChange("stopped");
            return;
        }
    
        // If we crash > 4 times in 4 minutes, reboot into recovery.
        boot_clock::time_point now = boot_clock::now();
        if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
            if (now < time_crashed_ + 4min) {
                if (++crash_count_ > 4) {
                    LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
                }
            } else {
                time_crashed_ = now;
                crash_count_ = 1;
            }
        }
    
        flags_ &= (~SVC_RESTART);
        flags_ |= SVC_RESTARTING;
    
        // Execute all onrestart commands for this service.
        onrestart_.ExecuteAllCommands();
    
        NotifyStateChange("restarting");
        return;
    }

    然后在init的main函数的死循环中,会调用Service::is_exec_service_running()函数,这个函数是直接return Service class的is_exec_service_running_ static bool变量(注意这个变量是static变量)。

    因为上面有将is_exec_service_running_变量设置为false,所以这个if条件成立,所以会调用RestartProcesses()。在这个函数中,会从ServiceList中取出每一个Service对象,然后判断其flags_变量中是否有SVC_RESTARTING flag,如果有,最终会调到这个service的Start()去再次启动这个service。

      

      

  • 相关阅读:
    XSS 防御方法总结
    IE浏览器兼容方案
    js 排序算法
    webapck 打包体积优化策略
    webapck 速度优化策略
    Grunt、Gulp和Webpack对比
    数据库中的undo日志、redo日志
    使用sysbench对mysql压力测试
    java -cp & java jar的区别
    使用BenchmarkSQL测试PostgreSQL
  • 原文地址:https://www.cnblogs.com/aspirs/p/11407611.html
Copyright © 2011-2022 走看看