pidfiles, graceful shutdown
This commit is contained in:
		
							parent
							
								
									8988cab87d
								
							
						
					
					
						commit
						34ddba17c1
					
				
							
								
								
									
										96
									
								
								main.go
								
								
								
								
							
							
						
						
									
										96
									
								
								main.go
								
								
								
								
							|  | @ -1,31 +1,58 @@ | ||||||
| package main | package main | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"encoding/binary" | ||||||
|  | 	"flag" | ||||||
| 	"log" | 	"log" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"os/exec" | ||||||
| 	"sync" | 	"sync" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var config Config | var config Config | ||||||
| 
 | 
 | ||||||
| const sockfile = "/tmp/gopaper.sock" | const sockfile = "/tmp/gopaper.sock" | ||||||
|  | const pidfilePath = "/tmp/gopaper.pid" | ||||||
| 
 | 
 | ||||||
| func main() { | func main() { | ||||||
|  | 	//SETUP FLAGS
 | ||||||
|  | 	var debugFlag = flag.Bool("debug", false, "help message for flag n") | ||||||
|  | 	flag.Parse() | ||||||
| 
 | 
 | ||||||
| 	//TODO:kill existing processes
 | 	//INITIALIZE CONFIG
 | ||||||
| 
 |  | ||||||
| 	log.SetFlags(log.LstdFlags | log.Lshortfile) |  | ||||||
| 
 |  | ||||||
| 	err := config.load() | 	err := config.load() | ||||||
| 	logfile, err := openLogfile() |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Println("failed to load config", err) | 		log.Println("unable to initialize config", err) | ||||||
| 		cleanExit(1) | 	} | ||||||
|  | 
 | ||||||
|  | 	//SETUP LOGGER
 | ||||||
|  | 	log.SetFlags(log.LstdFlags | log.Lshortfile) | ||||||
|  | 	if *debugFlag { | ||||||
|  | 		logfile, err := openLogfile() | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Println("failed to load config", err) | ||||||
|  | 			cleanExit(1) | ||||||
|  | 		} | ||||||
|  | 		log.SetOutput(logfile) | ||||||
| 	} | 	} | ||||||
| 	log.SetOutput(logfile) |  | ||||||
| 	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds) | 	log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds) | ||||||
| 	log.Println("Welcome to GoPaper!") | 	log.Println("Welcome to GoPaper!") | ||||||
| 
 | 
 | ||||||
|  | 	killPrevProc() | ||||||
|  | 	//create new pidfile
 | ||||||
|  | 	pid := os.Getpid() | ||||||
|  | 	pidfile, err := os.Create(pidfilePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println("error trying to create pidfile:", err) | ||||||
|  | 		cleanExit(1) | ||||||
|  | 	} | ||||||
|  | 	buf := new(bytes.Buffer) | ||||||
|  | 	err = binary.Write(buf, binary.LittleEndian, pid) | ||||||
|  | 	if err != nil { | ||||||
|  | 	} | ||||||
|  | 	pidfile.Write(buf.Bytes()) | ||||||
|  | 
 | ||||||
| 	var waitGroup sync.WaitGroup | 	var waitGroup sync.WaitGroup | ||||||
| 	waitGroup.Add(1) | 	waitGroup.Add(1) | ||||||
| 	slideshowDir := make(chan string) | 	slideshowDir := make(chan string) | ||||||
|  | @ -33,7 +60,7 @@ func main() { | ||||||
| 	func() { | 	func() { | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			if r := recover(); r != nil { | 			if r := recover(); r != nil { | ||||||
| 				log.Println("Panic recovered at top level. Closing gracefully.", r) | 				log.Println("Panic recovered at top level", r) | ||||||
| 				cleanExit(1) | 				cleanExit(1) | ||||||
| 			} | 			} | ||||||
| 		}() | 		}() | ||||||
|  | @ -63,6 +90,55 @@ func openLogfile() (*os.File, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func cleanExit(code int) { | func cleanExit(code int) { | ||||||
| 	os.Remove(sockfile) | 	if code == 1 { | ||||||
|  | 		log.Println("shutting down gracefully after errors") | ||||||
|  | 	} else { | ||||||
|  | 		log.Println("shutting down gracefully") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err := os.Remove(sockfile) | ||||||
|  | 	if err != nil && !os.IsNotExist(err) { | ||||||
|  | 		log.Printf("unable to remove sockfile at %v. Error: %v\n", sockfile, err) | ||||||
|  | 	} else if !os.IsNotExist(err) { | ||||||
|  | 		log.Println("sockfile removed") | ||||||
|  | 	} else { | ||||||
|  | 		log.Println("no need to remove sockfile -- it doesn't exist") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = os.Remove(pidfilePath) | ||||||
|  | 	if err != nil && !os.IsNotExist(err) { | ||||||
|  | 		log.Printf("unable to remove pidfile at %v. Error: %v\n", pidfilePath, err) | ||||||
|  | 	} else if !os.IsNotExist(err) { | ||||||
|  | 		log.Println("pidfile removed") | ||||||
|  | 	} else { | ||||||
|  | 		log.Println("no need to remove pidfile -- it doesn't exist") | ||||||
|  | 	} | ||||||
| 	os.Exit(code) | 	os.Exit(code) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func killPrevProc() error { | ||||||
|  | 	//check if pidfile already exists
 | ||||||
|  | 	if _, err := os.Stat(pidfilePath); os.IsNotExist(err) { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	//if it does, kill the process and delete the pidfile
 | ||||||
|  | 	prexPid, err := os.ReadFile(pidfilePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Println("unable to read pre-existing pidfile", err) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	//kill process
 | ||||||
|  | 	//BUG: kill command doesn't work. prexPid == []
 | ||||||
|  | 	err = exec.Command("kill", "-9", string(prexPid)).Run() | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Printf("unable to kill process %v\n", string(prexPid)) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	//remove pidfile
 | ||||||
|  | 	err = os.Remove(pidfilePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Printf("unable to remove pidfile %v\n", pidfilePath) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue