mirror of
				https://codeberg.org/forgejo/forgejo.git
				synced 2025-10-31 06:21:11 +00:00 
			
		
		
		
	Restore Graceful Restarting & Socket Activation (#7274)
* Prevent deadlock in indexer initialisation during graceful restart * Move from gracehttp to our own service to add graceful ssh * Add timeout for start of indexers and make hammer time configurable * Fix issue with re-initialization in indexer during tests * move the code to detect use of closed to graceful * Handle logs gracefully - add a pid suffix just before restart * Move to using a cond and a holder for indexers * use time.Since * Add some comments and attribution * update modules.txt * Use zero to disable timeout * Move RestartProcess to its own file * Add cleanup routine
This commit is contained in:
		
					parent
					
						
							
								4a290bd64c
							
						
					
				
			
			
				commit
				
					
						167e8f18da
					
				
			
		
					 45 changed files with 1202 additions and 2009 deletions
				
			
		
							
								
								
									
										67
									
								
								modules/graceful/restart.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								modules/graceful/restart.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | |||
| // Copyright 2019 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
| // This code is heavily inspired by the archived gofacebook/gracenet/net.go handler | ||||
| 
 | ||||
| package graceful | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // RestartProcess starts a new process passing it the active listeners. It | ||||
| // doesn't fork, but starts a new process using the same environment and | ||||
| // arguments as when it was originally started. This allows for a newly | ||||
| // deployed binary to be started. It returns the pid of the newly started | ||||
| // process when successful. | ||||
| func RestartProcess() (int, error) { | ||||
| 	listeners := getActiveListeners() | ||||
| 
 | ||||
| 	// Extract the fds from the listeners. | ||||
| 	files := make([]*os.File, len(listeners)) | ||||
| 	for i, l := range listeners { | ||||
| 		var err error | ||||
| 		// Now, all our listeners actually have File() functions so instead of | ||||
| 		// individually casting we just use a hacky interface | ||||
| 		files[i], err = l.(filer).File() | ||||
| 		if err != nil { | ||||
| 			return 0, err | ||||
| 		} | ||||
| 		// Remember to close these at the end. | ||||
| 		defer files[i].Close() | ||||
| 	} | ||||
| 
 | ||||
| 	// Use the original binary location. This works with symlinks such that if | ||||
| 	// the file it points to has been changed we will use the updated symlink. | ||||
| 	argv0, err := exec.LookPath(os.Args[0]) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Pass on the environment and replace the old count key with the new one. | ||||
| 	var env []string | ||||
| 	for _, v := range os.Environ() { | ||||
| 		if !strings.HasPrefix(v, listenFDs+"=") { | ||||
| 			env = append(env, v) | ||||
| 		} | ||||
| 	} | ||||
| 	env = append(env, fmt.Sprintf("%s=%d", listenFDs, len(listeners))) | ||||
| 
 | ||||
| 	allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}, files...) | ||||
| 	process, err := os.StartProcess(argv0, os.Args, &os.ProcAttr{ | ||||
| 		Dir:   originalWD, | ||||
| 		Env:   env, | ||||
| 		Files: allFiles, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	return process.Pid, nil | ||||
| } | ||||
| 
 | ||||
| type filer interface { | ||||
| 	File() (*os.File, error) | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue