func(m*ShimManager)startShim(ctxcontext.Context,bundle*Bundle,idstring,optsruntime.CreateOpts)(*shim,error){......shim,err:=b.Start(ctx,protobuf.FromAny(topts),func(){log.G(ctx).WithField("id",id).Info("shim disconnected")cleanupAfterDeadShim(context.Background(),id,ns,m.shims,m.events,b)// Remove self from the runtime task list. Even though the cleanupAfterDeadShim()
// would publish taskExit event, but the shim.Delete() would always failed with ttrpc
// disconnect and there is no chance to remove this dead task from runtime task lists.
// Thus it's better to delete it here.
m.shims.Delete(ctx,id)})iferr!=nil{returnnil,fmt.Errorf("start failed: %w",err)}returnshim,nil}
注意到,在b.Start 后面传入了一个回调函数
1
2
3
4
5
6
7
8
9
10
func(){log.G(ctx).WithField("id",id).Info("shim disconnected")cleanupAfterDeadShim(context.Background(),id,ns,m.shims,m.events,b)// Remove self from the runtime task list. Even though the cleanupAfterDeadShim()
// would publish taskExit event, but the shim.Delete() would always failed with ttrpc
// disconnect and there is no chance to remove this dead task from runtime task lists.
// Thus it's better to delete it here.
m.shims.Delete(ctx,id)}
func(b*binary)Delete(ctxcontext.Context)(*runtime.Exit,error){log.G(ctx).Info("cleaning up dead shim")...cmd,err:=client.Command(ctx,&client.CommandConfig{Runtime:b.runtime,Address:b.containerdAddress,TTRPCAddress:b.containerdTTRPCAddress,Path:bundlePath,Opts:nil,Args:[]string{"-id",b.bundle.ID,"-bundle",b.bundle.Path,"delete",},})...iferr:=cmd.Run();err!=nil{log.G(ctx).WithField("cmd",cmd).WithError(err).Error("failed to delete")returnnil,fmt.Errorf("%s: %w",errb.String(),err)}...}
[xiu-desktop] ~ n ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dc2362841897 docker.io/q946666800/runcdev:latest "/main-example" 4 hours ago Created runcdev
func(m*ShimManager)loadExistingTasks(ctxcontext.Context)error{nsDirs,err:=os.ReadDir(m.state)iferr!=nil{returnerr}// 遍历 ns
for_,nsd:=rangensDirs{if!nsd.IsDir(){continue}ns:=nsd.Name()// skip hidden directories
iflen(ns)>0&&ns[0]=='.'{continue}log.G(ctx).WithField("namespace",ns).Debug("loading tasks in namespace")iferr:=m.loadShims(namespaces.WithNamespace(ctx,ns));err!=nil{log.G(ctx).WithField("namespace",ns).WithError(err).Error("loading tasks in namespace")continue}iferr:=m.cleanupWorkDirs(namespaces.WithNamespace(ctx,ns));err!=nil{log.G(ctx).WithField("namespace",ns).WithError(err).Error("cleanup working directory in namespace")continue}}returnnil}
func(m*ShimManager)loadShims(ctxcontext.Context)error{ns,err:=namespaces.NamespaceRequired(ctx)iferr!=nil{returnerr}shimDirs,err:=os.ReadDir(filepath.Join(m.state,ns))iferr!=nil{returnerr}for_,sd:=rangeshimDirs{if!sd.IsDir(){continue}id:=sd.Name()// skip hidden directories
iflen(id)>0&&id[0]=='.'{continue}bundle,err:=LoadBundle(ctx,m.state,id)iferr!=nil{// fine to return error here, it is a programmer error if the context
// does not have a namespace
returnerr}// fast path
bf,err:=os.ReadDir(bundle.Path)iferr!=nil{bundle.Delete()log.G(ctx).WithError(err).Errorf("fast path read bundle path for %s",bundle.Path)continue}iflen(bf)==0{bundle.Delete()continue}var(runtimestring)// If we're on 1.6+ and specified custom path to the runtime binary, path will be saved in 'shim-binary-path' file.
ifdata,err:=os.ReadFile(filepath.Join(bundle.Path,"shim-binary-path"));err==nil{runtime=string(data)}elseiferr!=nil&&!os.IsNotExist(err){log.G(ctx).WithError(err).Error("failed to read `runtime` path from bundle")}// Query runtime name from metadata store
ifruntime==""{container,err:=m.containers.Get(ctx,id)iferr!=nil{log.G(ctx).WithError(err).Errorf("loading container %s",id)iferr:=mount.UnmountAll(filepath.Join(bundle.Path,"rootfs"),0);err!=nil{log.G(ctx).WithError(err).Errorf("failed to unmount of rootfs %s",id)}bundle.Delete()continue}runtime=container.Runtime.Name}runtime,err=m.resolveRuntimePath(runtime)iferr!=nil{bundle.Delete()log.G(ctx).WithError(err).Error("failed to resolve runtime path")continue}binaryCall:=shimBinary(bundle,shimBinaryConfig{runtime:runtime,address:m.containerdAddress,ttrpcAddress:m.containerdTTRPCAddress,schedCore:m.schedCore,})instance,err:=loadShim(ctx,bundle,func(){log.G(ctx).WithField("id",id).Info("shim disconnected")cleanupAfterDeadShim(context.Background(),id,ns,m.shims,m.events,binaryCall)// Remove self from the runtime task list.
m.shims.Delete(ctx,id)})// 在这里进入 cleanupAfterDeadShim,进行清理工作
iferr!=nil{cleanupAfterDeadShim(ctx,id,ns,m.shims,m.events,binaryCall)continue}shim:=newShimTask(instance)// There are 3 possibilities for the loaded shim here:
// 1. It could be a shim that is running a task.
// 2. It could be a sandbox shim.
// 3. Or it could be a shim that was created for running a task but
// something happened (probably a containerd crash) and the task was never
// created. This shim process should be cleaned up here. Look at
// containerd/containerd#6860 for further details.
_,sgetErr:=m.sandboxStore.Get(ctx,id)pInfo,pidErr:=shim.Pids(ctx)ifsgetErr!=nil&&errors.Is(sgetErr,errdefs.ErrNotFound)&&(len(pInfo)==0||errors.Is(pidErr,errdefs.ErrNotFound)){log.G(ctx).WithField("id",id).Info("cleaning leaked shim process")// We are unable to get Pids from the shim and it's not a sandbox
// shim. We should clean it up her.
// No need to do anything for removeTask since we never added this shim.
shim.delete(ctx,false,func(ctxcontext.Context,idstring){})}else{m.shims.Add(ctx,shim.ShimInstance)}}returnnil}
[xiu-desktop] ~ n ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7206459bb2db docker.io/q946666800/runcdev:latest "/main-example" 4 minutes ago Created runcdev