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"
 | 
						"github.com/pterodactyl/wings/environment"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,23 +116,40 @@ func (e *Environment) Start() error {
 | 
				
			||||||
	return e.Attach()
 | 
						return e.Attach()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stops the container that the server is running in. This will allow up to 30 seconds to pass
 | 
					// Stop stops the container that the server is running in. This will allow up to
 | 
				
			||||||
// before the container is forcefully terminated if we are trying to stop it without using a command
 | 
					// 30 seconds to pass before the container is forcefully terminated if we are
 | 
				
			||||||
// sent into the instance.
 | 
					// 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
 | 
					// You most likely want to be using WaitForStop() rather than this function,
 | 
				
			||||||
// as soon as the command is sent, rather than waiting for the process to be completed stopped.
 | 
					// 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 {
 | 
					func (e *Environment) Stop() error {
 | 
				
			||||||
	e.mu.RLock()
 | 
						e.mu.RLock()
 | 
				
			||||||
	s := e.meta.Stop
 | 
						s := e.meta.Stop
 | 
				
			||||||
	e.mu.RUnlock()
 | 
						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 == "" || s.Type == api.ProcessStopSignal {
 | 
				
			||||||
		if s.Type == "" {
 | 
							if s.Type == "" {
 | 
				
			||||||
			log.WithField("container_id", e.Id).Warn("no stop configuration detected for environment, using termination procedure")
 | 
								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
 | 
						// 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
 | 
						t := time.Second * 30
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := e.client.ContainerStop(context.Background(), e.Id, &t); err != nil {
 | 
						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
 | 
							// If the container does not exist just mark the process as stopped and return without
 | 
				
			||||||
		// an error.
 | 
							// an error.
 | 
				
			||||||
		if client.IsErrNotFound(err) {
 | 
							if client.IsErrNotFound(err) {
 | 
				
			||||||
			e.SetStream(nil)
 | 
								e.SetStream(nil)
 | 
				
			||||||
			e.SetState(environment.ProcessOfflineState)
 | 
								e.SetState(environment.ProcessOfflineState)
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Attempts to gracefully stop a server using the defined stop command. If the server
 | 
					// WaitForStop attempts to gracefully stop a server using the defined stop
 | 
				
			||||||
// does not stop after seconds have passed, an error will be returned, or the instance
 | 
					// command. If the server does not stop after seconds have passed, an error will
 | 
				
			||||||
// will be terminated forcefully depending on the value of the second argument.
 | 
					// 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 {
 | 
					func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
 | 
				
			||||||
	if err := e.Stop(); err != nil {
 | 
						if err := e.Stop(); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -211,7 +227,7 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
 | 
				
			||||||
	return nil
 | 
						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 {
 | 
					func (e *Environment) Terminate(signal os.Signal) error {
 | 
				
			||||||
	c, err := e.client.ContainerInspect(context.Background(), e.Id)
 | 
						c, err := e.client.ContainerInspect(context.Background(), e.Id)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user