github.com/apptainer/singularity@v3.1.1+incompatible/internal/app/singularity/oci_kill_linux.go (about)

     1  // Copyright (c) 2018-2019, Sylabs Inc. All rights reserved.
     2  // This software is licensed under a 3-clause BSD license. Please consult the
     3  // LICENSE.md file distributed with the sources of this project regarding your
     4  // rights to use or distribute this software.
     5  
     6  package singularity
     7  
     8  import (
     9  	"fmt"
    10  	"io"
    11  	"syscall"
    12  	"time"
    13  
    14  	"github.com/sylabs/singularity/internal/pkg/util/signal"
    15  	"github.com/sylabs/singularity/pkg/ociruntime"
    16  	"github.com/sylabs/singularity/pkg/util/unix"
    17  )
    18  
    19  // OciKill kills container process
    20  func OciKill(containerID string, killSignal string, killTimeout int) error {
    21  	// send signal to the instance
    22  	state, err := getState(containerID)
    23  	if err != nil {
    24  		return err
    25  	}
    26  
    27  	if state.Status != ociruntime.Created && state.Status != ociruntime.Running {
    28  		return fmt.Errorf("cannot kill '%s', the state of the container must be created or running", containerID)
    29  	}
    30  
    31  	sig := syscall.SIGTERM
    32  
    33  	if killSignal != "" {
    34  		sig, err = signal.Convert(killSignal)
    35  		if err != nil {
    36  			return err
    37  		}
    38  	}
    39  
    40  	if killTimeout > 0 {
    41  		c, err := unix.Dial(state.ControlSocket)
    42  		if err != nil {
    43  			return fmt.Errorf("failed to connect to control socket")
    44  		}
    45  		defer c.Close()
    46  
    47  		killed := make(chan bool, 1)
    48  
    49  		go func() {
    50  			// wait runtime close socket connection for ACK
    51  			d := make([]byte, 1)
    52  			if _, err := c.Read(d); err == io.EOF {
    53  				killed <- true
    54  			}
    55  		}()
    56  
    57  		if err := syscall.Kill(state.Pid, sig); err != nil {
    58  			return err
    59  		}
    60  
    61  		select {
    62  		case <-killed:
    63  		case <-time.After(time.Duration(killTimeout) * time.Second):
    64  			return syscall.Kill(state.Pid, syscall.SIGKILL)
    65  		}
    66  	} else {
    67  		return syscall.Kill(state.Pid, sig)
    68  	}
    69  
    70  	return nil
    71  }