Prevent zombie processes (#16314)
Unfortunately go doesn't always ensure that execd processes are completely waited for. On linux this means that zombie processes can occur. This PR ensures that these are waited for by using signal notifier in serv and passing a context elsewhere. Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		
							parent
							
								
									365c4e9316
								
							
						
					
					
						commit
						302e8b6d02
					
				
					 3 changed files with 34 additions and 4 deletions
				
			
		
							
								
								
									
										26
									
								
								cmd/serv.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								cmd/serv.go
									
									
									
									
									
								
							|  | @ -6,14 +6,17 @@ | |||
| package cmd | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"os/signal" | ||||
| 	"regexp" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models" | ||||
|  | @ -273,12 +276,31 @@ func runServ(c *cli.Context) error { | |||
| 		verb = strings.Replace(verb, "-", " ", 1) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx, cancel := context.WithCancel(context.Background()) | ||||
| 	defer cancel() | ||||
| 	go func() { | ||||
| 		// install notify
 | ||||
| 		signalChannel := make(chan os.Signal, 1) | ||||
| 
 | ||||
| 		signal.Notify( | ||||
| 			signalChannel, | ||||
| 			syscall.SIGINT, | ||||
| 			syscall.SIGTERM, | ||||
| 		) | ||||
| 		select { | ||||
| 		case <-signalChannel: | ||||
| 		case <-ctx.Done(): | ||||
| 		} | ||||
| 		cancel() | ||||
| 		signal.Reset() | ||||
| 	}() | ||||
| 
 | ||||
| 	var gitcmd *exec.Cmd | ||||
| 	verbs := strings.Split(verb, " ") | ||||
| 	if len(verbs) == 2 { | ||||
| 		gitcmd = exec.Command(verbs[0], verbs[1], repoPath) | ||||
| 		gitcmd = exec.CommandContext(ctx, verbs[0], verbs[1], repoPath) | ||||
| 	} else { | ||||
| 		gitcmd = exec.Command(verb, repoPath) | ||||
| 		gitcmd = exec.CommandContext(ctx, verb, repoPath) | ||||
| 	} | ||||
| 
 | ||||
| 	gitcmd.Dir = setting.RepoRootPath | ||||
|  |  | |||
							
								
								
									
										10
									
								
								modules/markup/external/external.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								modules/markup/external/external.go
									
									
									
									
										vendored
									
									
								
							|  | @ -5,6 +5,7 @@ | |||
| package external | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
|  | @ -15,6 +16,7 @@ import ( | |||
| 
 | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/markup" | ||||
| 	"code.gitea.io/gitea/modules/process" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
|  | @ -96,7 +98,13 @@ func (p *Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io. | |||
| 		args = append(args, f.Name()) | ||||
| 	} | ||||
| 
 | ||||
| 	cmd := exec.Command(commands[0], args...) | ||||
| 	processCtx, cancel := context.WithCancel(ctx.Ctx) | ||||
| 	defer cancel() | ||||
| 
 | ||||
| 	pid := process.GetManager().Add(fmt.Sprintf("Render [%s] for %s", commands[0], ctx.URLPrefix), cancel) | ||||
| 	defer process.GetManager().Remove(pid) | ||||
| 
 | ||||
| 	cmd := exec.CommandContext(processCtx, commands[0], args...) | ||||
| 	cmd.Env = append( | ||||
| 		os.Environ(), | ||||
| 		"GITEA_PREFIX_SRC="+ctx.URLPrefix, | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ func sessionHandler(session ssh.Session) { | |||
| 
 | ||||
| 	args := []string{"serv", "key-" + keyID, "--config=" + setting.CustomConf} | ||||
| 	log.Trace("SSH: Arguments: %v", args) | ||||
| 	cmd := exec.Command(setting.AppPath, args...) | ||||
| 	cmd := exec.CommandContext(session.Context(), setting.AppPath, args...) | ||||
| 	cmd.Env = append( | ||||
| 		os.Environ(), | ||||
| 		"SSH_ORIGINAL_COMMAND="+command, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue