diff --git a/admin.go b/admin.go index d64a51b3..568d86a7 100644 --- a/admin.go +++ b/admin.go @@ -107,7 +107,6 @@ func listConf(rw http.ResponseWriter, r *http.Request) { fmt.Fprintln(rw, "MaxMemory:", MaxMemory) fmt.Fprintln(rw, "EnableGzip:", EnableGzip) fmt.Fprintln(rw, "DirectoryIndex:", DirectoryIndex) - fmt.Fprintln(rw, "EnableHotUpdate:", EnableHotUpdate) fmt.Fprintln(rw, "HttpServerTimeOut:", HttpServerTimeOut) fmt.Fprintln(rw, "ErrorsShow:", ErrorsShow) fmt.Fprintln(rw, "XSRFKEY:", XSRFKEY) diff --git a/app.go b/app.go index 32783df6..e6ca4bc7 100644 --- a/app.go +++ b/app.go @@ -45,7 +45,7 @@ func (app *App) Run() { err error l net.Listener ) - endRunning := make(chan bool) + endRunning := make(chan bool, 1) if UseFcgi { if HttpPort == 0 { @@ -58,56 +58,35 @@ func (app *App) Run() { } err = fcgi.Serve(l, app.Handlers) } else { - if EnableHotUpdate { - server := &http.Server{ - Handler: app.Handlers, - ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, - WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, - } - laddr, err := net.ResolveTCPAddr("tcp", addr) - if nil != err { - BeeLogger.Critical("ResolveTCPAddr:", err) - } - l, err = GetInitListener(laddr) - if err == nil { - theStoppable = newStoppable(l) - err = server.Serve(theStoppable) - if err == nil { - theStoppable.wg.Wait() - err = CloseSelf() + s := &http.Server{ + Addr: addr, + Handler: app.Handlers, + ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, + WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, + } + if EnableHttpTLS { + go func() { + if HttpsPort != 0 { + s.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort) } - } - } else { - s := &http.Server{ - Addr: addr, - Handler: app.Handlers, - ReadTimeout: time.Duration(HttpServerTimeOut) * time.Second, - WriteTimeout: time.Duration(HttpServerTimeOut) * time.Second, - } - if EnableHttpTLS { - go func() { - if HttpsPort != 0 { - s.Addr = fmt.Sprintf("%s:%d", HttpAddr, HttpsPort) - } - err := s.ListenAndServeTLS(HttpCertFile, HttpKeyFile) - if err != nil { - BeeLogger.Critical("ListenAndServeTLS: ", err) - time.Sleep(100 * time.Microsecond) - endRunning <- true - } - }() - } + err := s.ListenAndServeTLS(HttpCertFile, HttpKeyFile) + if err != nil { + BeeLogger.Critical("ListenAndServeTLS: ", err) + time.Sleep(100 * time.Microsecond) + endRunning <- true + } + }() + } - if EnableHttpListen { - go func() { - err := s.ListenAndServe() - if err != nil { - BeeLogger.Critical("ListenAndServe: ", err) - time.Sleep(100 * time.Microsecond) - endRunning <- true - } - }() - } + if EnableHttpListen { + go func() { + err := s.ListenAndServe() + if err != nil { + BeeLogger.Critical("ListenAndServe: ", err) + time.Sleep(100 * time.Microsecond) + endRunning <- true + } + }() } } diff --git a/config.go b/config.go index deb34464..1a42409b 100644 --- a/config.go +++ b/config.go @@ -56,7 +56,6 @@ var ( MaxMemory int64 EnableGzip bool // flag of enable gzip DirectoryIndex bool // flag of display directory index. default is false. - EnableHotUpdate bool // flag of hot update checking by app self. default is false. HttpServerTimeOut int64 ErrorsShow bool // flag of show errors in page. if true, show error and trace info in page rendered with error template. XSRFKEY string // xsrf hash salt string. @@ -101,6 +100,7 @@ func init() { // set this to 0.0.0.0 to make this app available to externally EnableHttpListen = true //default enable http Listen + HttpAddr = "" HttpPort = 8080 @@ -254,10 +254,6 @@ func ParseConfig() (err error) { DirectoryIndex = directoryindex } - if hotupdate, err := AppConfig.Bool("HotUpdate"); err == nil { - EnableHotUpdate = hotupdate - } - if timeout, err := AppConfig.Int64("HttpServerTimeOut"); err == nil { HttpServerTimeOut = timeout } diff --git a/reload.go b/reload.go deleted file mode 100644 index fc4d3f9f..00000000 --- a/reload.go +++ /dev/null @@ -1,169 +0,0 @@ -// Beego (http://beego.me/) -// @description beego is an open-source, high-performance web framework for the Go programming language. -// @link http://github.com/astaxie/beego for the canonical source repository -// @license http://github.com/astaxie/beego/blob/master/LICENSE -// @authors astaxie - -package beego - -import ( - "errors" - "fmt" - "log" - "net" - "os" - "os/exec" - "os/signal" - "reflect" - "strconv" - "sync" - //"syscall" -) - -const ( - // An environment variable when restarting application http listener. - FDKey = "BEEGO_HOT_FD" -) - -// Export an error equivalent to net.errClosing for use with Accept during -// a graceful exit. -var ErrClosing = errors.New("use of closed network connection") -var ErrInitStart = errors.New("init from") - -// Allows for us to notice when the connection is closed. -type conn struct { - net.Conn - wg *sync.WaitGroup - isclose bool - lock *sync.Mutex -} - -// Close current processing connection. -func (c conn) Close() error { - c.lock.Lock() - defer c.lock.Unlock() - err := c.Conn.Close() - if !c.isclose && err == nil { - c.wg.Done() - c.isclose = true - } - return err -} - -type stoppableListener struct { - net.Listener - count int64 - stopped bool - wg sync.WaitGroup -} - -var theStoppable *stoppableListener - -func newStoppable(l net.Listener) (sl *stoppableListener) { - sl = &stoppableListener{Listener: l} - - // this goroutine monitors the channel. Can't do this in - // Accept (below) because once it enters sl.Listener.Accept() - // it blocks. We unblock it by closing the fd it is trying to - // accept(2) on. - go func() { - WaitSignal(l) - sl.stopped = true - sl.Listener.Close() - }() - return -} - -// Set stopped Listener to accept requests again. -// it returns the accepted and closable connection or error. -func (sl *stoppableListener) Accept() (c net.Conn, err error) { - c, err = sl.Listener.Accept() - if err != nil { - return - } - sl.wg.Add(1) - // Wrap the returned connection, so that we can observe when - // it is closed. - c = conn{Conn: c, wg: &sl.wg} - - return -} - -// Listener waits signal to kill or interrupt then restart. -func WaitSignal(l net.Listener) error { - ch := make(chan os.Signal, 1) - signal.Notify(ch, os.Interrupt, os.Kill) - for { - sig := <-ch - log.Println(sig.String()) - switch sig { - - case os.Kill: - return nil - case os.Interrupt: - err := Restart(l) - if nil != err { - return err - } - return nil - } - } -} - -// Kill current running os process. -func CloseSelf() error { - ppid := os.Getpid() - if ppid == 1 { // init provided sockets, for example systemd - return nil - } - p, err := os.FindProcess(ppid) - if err != nil { - return err - } - return p.Kill() -} - -// Re-exec this image without dropping the listener passed to this function. -func Restart(l net.Listener) error { - argv0, err := exec.LookPath(os.Args[0]) - if nil != err { - return err - } - wd, err := os.Getwd() - if nil != err { - return err - } - v := reflect.ValueOf(l).Elem().FieldByName("fd").Elem() - fd := uintptr(v.FieldByName("sysfd").Int()) - allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}, - os.NewFile(fd, string(v.FieldByName("sysfile").String()))) - - p, err := os.StartProcess(argv0, os.Args, &os.ProcAttr{ - Dir: wd, - Env: append(os.Environ(), fmt.Sprintf("%s=%d", FDKey, fd)), - Files: allFiles, - }) - if nil != err { - return err - } - log.Printf("spawned child %d\n", p.Pid) - return nil -} - -// Get current net.Listen in running process. -func GetInitListener(tcpaddr *net.TCPAddr) (l net.Listener, err error) { - countStr := os.Getenv(FDKey) - if countStr == "" { - return net.ListenTCP("tcp", tcpaddr) - } - count, err := strconv.Atoi(countStr) - if err != nil { - return nil, err - } - f := os.NewFile(uintptr(count), "listen socket") - l, err = net.FileListener(f) - if err != nil { - return nil, err - } - return l, nil -}