Docker源码分析
上QQ阅读APP看书,第一时间看更新

3.3.4 设置engine的信号捕获

Docker在包engine中执行完Engine对象的创建与初始化之后,回到mainDaemon()函数的运行,紧接着执行的代码为:

signal.Trap(eng.Shutdown)

Docker Daemon作为Linux操作系统上的一个后台进程,原则上应该具备处理信号的能力。信号处理能力的存在,能保障Docker管理员可以通过向Docker Daemon发送信号的方式,管理Docker Daemon的运行。

再来看以上代码则不难理解其中的含义:在Docker Daemon的运行中,设置捕获特定信号后的处理方法,特定信号有SIGINT、SIGTERM以及SIGQUIT;当程序捕获SIGINT或者SIGTERM信号时,执行相应的善后操作,最后保证Docker Daemon程序退出。

该部分代码的实现位于./docker/docker/pkg/signal/trap.go。实现的流程分为以下4个步骤:

1)创建并设置一个channel,用于发送信号通知。

2)定义signals数组变量,初始值为os.SIGINT,os.SIGTERM;若环境变量DEBUG为空,则添加os.SIGQUIT至signals数组。

3)通过gosignal.Notify(c,signals...)中Notify函数来实现将接收到的signal信号传递给c。需要注意的是只有signals中被罗列出的信号才会被传递给c,其余信号会被直接忽略。

4)创建一个goroutine来处理具体的signal信号,当信号类型为os.Interrupt或者syscall.SIGTERM时,执行传入Trap函数的具体执行方法,形参为cleanup(),实参为eng.Shutdown。

Shutdown()函数的定义位于./docker/docker/engine/engine.go#L153-L199,主要完成的任务是:Docker Daemon关闭时,做一些必要的善后工作。

善后工作主要有以下4项:

□ Docker Daemon不再接受任何新的Job。

□ Docker Daemon等待所有存活的Job执行完毕。

□ Docker Daemon调用所有shutdown的处理方法。

□ 在15秒时间内,若所有的handler执行完毕,则Shutdown()函数返回,否则强制返回。

由于在signal.Trap(eng.Shutdown)函数的具体实现中,一旦程序接收到相应的信号,则会执行eng.Shutdown这个函数,在执行完eng.Shutdown之后,随即执行os.Exit(0),完成当前整个Docker Daemon程序的退出。源码实现位于./docker/docker/pkg/signal/trap.go#L33-L47。