func()

in lambda/rapid/shutdown.go [305:368]


func (s *shutdownContext) shutdown(execCtx *rapidContext, deadlineNs int64, reason string) (int64, bool, error) {
	var err error
	s.setShuttingDown(true)
	defer s.setShuttingDown(false)

	// Fatal errors such as Runtime exit and Extension.Crash
	// are ignored by the events watcher when shutting down
	execCtx.appCtx.Delete(appctx.AppCtxFirstFatalErrorKey)

	runtimeDomainProfiler := &metering.ExtensionsResetDurationProfiler{}

	// We do not spend any compute time on runtime graceful shutdown if there are no agents
	if execCtx.registrationService.CountAgents() == 0 {
		name := fmt.Sprintf("%s-%d", runtimeProcessName, execCtx.runtimeDomainGeneration)

		_, found := s.getExitedChannel(name)

		if found {
			log.Debug("SIGKILLing the runtime as no agents are registered.")
			err = execCtx.supervisor.Kill(context.Background(), &supvmodel.KillRequest{
				Domain:   RuntimeDomain,
				Name:     name,
				Deadline: time.Now().Add(time.Millisecond * supervisorBlockingMaxMillis),
			})
			if err != nil {
				// We are not reporting the error upstream because we will anyway
				// shut the domain out at the end of the shutdown sequence
				log.WithError(err).Warn("Failed sending Kill signal to runtime")
			}
		} else {
			log.Debugf("Could not find runtime process %s in processes map. Already exited/never started", name)
		}
	} else {
		mono := metering.Monotime()
		availableNs := deadlineNs - mono

		if availableNs < 0 {
			log.Warnf("Deadline is in the past: %v, %v, %v", mono, deadlineNs, availableNs)
			availableNs = 0
		}

		start := time.Now()

		runtimeDeadline := start.Add(time.Duration(float64(availableNs) * runtimeDeadlineShare))
		agentsDeadline := start.Add(time.Duration(availableNs))

		runtimeDomainProfiler.AvailableNs = availableNs
		runtimeDomainProfiler.Start()

		s.shutdownRuntime(execCtx, start, runtimeDeadline)
		s.shutdownAgents(execCtx, start, agentsDeadline, reason)

		runtimeDomainProfiler.NumAgentsRegisteredForShutdown = len(s.agentsAwaitingExit)
	}

	log.Info("Waiting for runtime domain processes termination")
	if err := s.clearExitedChannel(); err != nil {
		log.Error(err)
	}

	runtimeDomainProfiler.Stop()
	extensionsResetMs, timeout := runtimeDomainProfiler.CalculateExtensionsResetMs()
	return extensionsResetMs, timeout, err
}