2023-11-27 11:02:25 +00:00
|
|
|
/**
|
|
|
|
# Copyright 2020-2023 NVIDIA CORPORATION
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
**/
|
|
|
|
|
2024-09-27 08:59:01 +00:00
|
|
|
package containerd
|
2023-11-27 11:02:25 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"syscall"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
reloadBackoff = 5 * time.Second
|
|
|
|
maxReloadAttempts = 6
|
|
|
|
|
|
|
|
socketMessageToGetPID = ""
|
|
|
|
)
|
|
|
|
|
|
|
|
// SignalContainerd sends a SIGHUP signal to the containerd daemon
|
|
|
|
func SignalContainerd(socket string) error {
|
|
|
|
log.Infof("Sending SIGHUP signal to containerd")
|
|
|
|
|
|
|
|
// Wrap the logic to perform the SIGHUP in a function so we can retry it on failure
|
|
|
|
retriable := func() error {
|
|
|
|
conn, err := net.Dial("unix", socket)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to dial: %v", err)
|
|
|
|
}
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
|
|
sconn, err := conn.(*net.UnixConn).SyscallConn()
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to get syscall connection: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err1 := sconn.Control(func(fd uintptr) {
|
|
|
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
|
|
|
|
})
|
|
|
|
if err1 != nil {
|
|
|
|
return fmt.Errorf("unable to issue call on socket fd: %v", err1)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to SetsockoptInt on socket fd: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, _, err = conn.(*net.UnixConn).WriteMsgUnix([]byte(socketMessageToGetPID), nil, nil)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to WriteMsgUnix on socket fd: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
oob := make([]byte, 1024)
|
|
|
|
_, oobn, _, _, err := conn.(*net.UnixConn).ReadMsgUnix(nil, oob)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to ReadMsgUnix on socket fd: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
oob = oob[:oobn]
|
|
|
|
scm, err := syscall.ParseSocketControlMessage(oob)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to ParseSocketControlMessage from message received on socket fd: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ucred, err := syscall.ParseUnixCredentials(&scm[0])
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to ParseUnixCredentials from message received on socket fd: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = syscall.Kill(int(ucred.Pid), syscall.SIGHUP)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("unable to send SIGHUP to 'containerd' process: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to send a SIGHUP up to maxReloadAttempts times
|
|
|
|
var err error
|
|
|
|
for i := 0; i < maxReloadAttempts; i++ {
|
|
|
|
err = retriable()
|
|
|
|
if err == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if i == maxReloadAttempts-1 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
log.Warningf("Error signaling containerd, attempt %v/%v: %v", i+1, maxReloadAttempts, err)
|
|
|
|
time.Sleep(reloadBackoff)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
log.Warningf("Max retries reached %v/%v, aborting", maxReloadAttempts, maxReloadAttempts)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Infof("Successfully signaled containerd")
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|