func main() { // Daemonizing echo server application. switch isDaemon, err := daemon.Daemonize(); { case !isDaemon: return case err != nil: log.Fatalf("main(): could not start daemon, reason -> %s", err.Error()) } // From now we are running in daemon process. // Listen on TCP port 2000 on all interfaces. l, err := net.Listen("tcp", ":2000") if err != nil { log.Fatal(err) } defer l.Close() for { // Wait for a connection. conn, err := l.Accept() if err != nil { log.Fatal(err) } // Handle the connection in a new goroutine. // The loop then returns to accepting, so that // multiple connections may be served concurrently. go func(c net.Conn) { // Echo all incoming data. io.Copy(c, c) // Shut down the connection. c.Close() }(conn) } }
func main() { // Daemonizing http server. switch isDaemon, err := daemon.Daemonize(); { case !isDaemon: return case err != nil: log.Fatalf("main(): could not start daemon, reason -> %s", err.Error()) } // From now we are running in daemon process. // Starting listen tcp on 8888 port. listener, hasPrev, err := previousListener() if err != nil { if hasPrev { log.Fatalf( "main(): failed to resume listener, reason -> %s", err.Error(), ) } if listener, err = net.Listen("tcp", ":8888"); err != nil { log.Fatalf("main(): failed to listen, reason -> %s", err.Error()) } } httpServer := &http.Server{} // Listen OS signals in separate goroutine. go listenSignals(listener, httpServer) // Creating a simple one-page http server. PID := os.Getppid() waiter := new(sync.WaitGroup) http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { waiter.Add(1) fmt.Fprintf(w, "Hi! I am graceful http server! My PID is %d", PID) waiter.Done() }) waiter.Add(1) go func() { if err := httpServer.Serve(listener); err != nil && !isErrClosing(err) { log.Fatalf( "main(): failed to serve listener, reason -> %s", err.Error(), ) } waiter.Done() }() // If was started by "reload" option. if hasPrev { if err := syscall.Kill(PID, syscall.SIGUSR1); err != nil { log.Printf( "main(): failed to notify parent daemon procces, reason -> %s", err.Error(), ) } } // Waiting all requests to be finished. waiter.Wait() }
func main() { // Daemonizing http server. switch isDaemon, err := daemon.Daemonize(); { case !isDaemon: return case err != nil: log.Fatalf("main(): could not start daemon, reason -> %s", err.Error()) } // From now we are running in daemon process. // Imitating "heavy" initialization phase. time.Sleep(time.Second) // Creating "Hello, World!" HTTP server. http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("Hello, World!")) }) listener, err := net.Listen("tcp", ":8889") if err != nil { log.Fatalf( "main(): failed to listen on port :8889, reason -> %s", err.Error(), ) } defer listener.Close() stoppedRunning := make(chan struct{}) go func() { defer close(stoppedRunning) if err := http.Serve(listener, nil); err != nil && !isErrClosing(err) { log.Fatalf( "main(): failed to serve listener, reason -> %s", err.Error(), ) } }() // Imitating more "heavy" initialization tasks. time.Sleep(time.Second) // Notifying parent process that we have started successfully. if err := syscall.Kill(os.Getppid(), syscall.SIGUSR1); err != nil { log.Fatalf( "main(): notifying parent proccess failed, reason -> %s", err.Error(), ) } // Preventing main goroutine from closing while HTTP server is running. <-stoppedRunning }