Support some additional signal types for stopping a server; ref pterodactyl/panel#3042
This commit is contained in:
		
							parent
							
								
									df721f45f8
								
							
						
					
					
						commit
						225f8aa904
					
				| 
						 | 
				
			
			@ -11,6 +11,7 @@ import (
 | 
			
		|||
	"github.com/pterodactyl/wings/environment"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,23 +116,40 @@ func (e *Environment) Start() error {
 | 
			
		|||
	return e.Attach()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stops the container that the server is running in. This will allow up to 30 seconds to pass
 | 
			
		||||
// before the container is forcefully terminated if we are trying to stop it without using a command
 | 
			
		||||
// sent into the instance.
 | 
			
		||||
// Stop stops the container that the server is running in. This will allow up to
 | 
			
		||||
// 30 seconds to pass before the container is forcefully terminated if we are
 | 
			
		||||
// trying to stop it without using a command sent into the instance.
 | 
			
		||||
//
 | 
			
		||||
// You most likely want to be using WaitForStop() rather than this function, since this will return
 | 
			
		||||
// as soon as the command is sent, rather than waiting for the process to be completed stopped.
 | 
			
		||||
// You most likely want to be using WaitForStop() rather than this function,
 | 
			
		||||
// since this will return as soon as the command is sent, rather than waiting
 | 
			
		||||
// for the process to be completed stopped.
 | 
			
		||||
//
 | 
			
		||||
// TODO: pass context through from the server instance.
 | 
			
		||||
func (e *Environment) Stop() error {
 | 
			
		||||
	e.mu.RLock()
 | 
			
		||||
	s := e.meta.Stop
 | 
			
		||||
	e.mu.RUnlock()
 | 
			
		||||
 | 
			
		||||
	// A native "stop" as the Type field value will just skip over all of this
 | 
			
		||||
	// logic and end up only executing the container stop command (which may or
 | 
			
		||||
	// may not work as expected).
 | 
			
		||||
	if s.Type == "" || s.Type == api.ProcessStopSignal {
 | 
			
		||||
		if s.Type == "" {
 | 
			
		||||
			log.WithField("container_id", e.Id).Warn("no stop configuration detected for environment, using termination procedure")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return e.Terminate(os.Kill)
 | 
			
		||||
		signal := os.Kill
 | 
			
		||||
		// Handle a few common cases, otherwise just fall through and just pass along
 | 
			
		||||
		// the os.Kill signal to the process.
 | 
			
		||||
		switch strings.ToUpper(s.Value) {
 | 
			
		||||
		case "SIGABRT":
 | 
			
		||||
			signal = syscall.SIGABRT
 | 
			
		||||
		case "SIGINT":
 | 
			
		||||
			signal = syscall.SIGINT
 | 
			
		||||
		case "SIGTERM":
 | 
			
		||||
			signal = syscall.SIGTERM
 | 
			
		||||
		}
 | 
			
		||||
		return e.Terminate(signal)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If the process is already offline don't switch it back to stopping. Just leave it how
 | 
			
		||||
| 
						 | 
				
			
			@ -147,26 +165,24 @@ func (e *Environment) Stop() error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	t := time.Second * 30
 | 
			
		||||
 | 
			
		||||
	if err := e.client.ContainerStop(context.Background(), e.Id, &t); err != nil {
 | 
			
		||||
		// If the container does not exist just mark the process as stopped and return without
 | 
			
		||||
		// an error.
 | 
			
		||||
		if client.IsErrNotFound(err) {
 | 
			
		||||
			e.SetStream(nil)
 | 
			
		||||
			e.SetState(environment.ProcessOfflineState)
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attempts to gracefully stop a server using the defined stop command. If the server
 | 
			
		||||
// does not stop after seconds have passed, an error will be returned, or the instance
 | 
			
		||||
// will be terminated forcefully depending on the value of the second argument.
 | 
			
		||||
// WaitForStop attempts to gracefully stop a server using the defined stop
 | 
			
		||||
// command. If the server does not stop after seconds have passed, an error will
 | 
			
		||||
// be returned, or the instance will be terminated forcefully depending on the
 | 
			
		||||
// value of the second argument.
 | 
			
		||||
func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
 | 
			
		||||
	if err := e.Stop(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +227,7 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Forcefully terminates the container using the signal passed through.
 | 
			
		||||
// Terminate forcefully terminates the container using the signal provided.
 | 
			
		||||
func (e *Environment) Terminate(signal os.Signal) error {
 | 
			
		||||
	c, err := e.client.ContainerInspect(context.Background(), e.Id)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user