Capstan is a Golang web framework that shares some similarities with others in its segment.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.1KB

  1. package capstan
  2. import (
  3. "encoding/json"
  4. "os"
  5. )
  6. // Relaunch the current binary inheriting all socket connection file
  7. // descriptors.
  8. //
  9. // This should be called from a goroutine. Parent/child process management is
  10. // not handled by this function.
  11. func Relaunch() error {
  12. env := &fdenv{
  13. Sockets: make([]*fdencode, 0),
  14. ParentPID: os.Getpid(),
  15. Addrs: make(map[string]string),
  16. }
  17. files, err := fds.Files()
  18. if err != nil {
  19. return err
  20. }
  21. for _, file := range files {
  22. env.Sockets = append(env.Sockets, &fdencode{file.fp.Name(), file.fd})
  23. }
  24. env.Addrs = fds.addrmap
  25. buf, _ := json.Marshal(env)
  26. cwd, _ := os.Getwd()
  27. exe, _ := os.Executable()
  28. os.Setenv("CAPSTAN_SOCKETS", string(buf))
  29. proc, err := os.StartProcess(exe, os.Args, &os.ProcAttr{
  30. Dir: cwd,
  31. Env: os.Environ(),
  32. Files: []*os.File{
  33. os.Stdin,
  34. os.Stdout,
  35. os.Stderr,
  36. },
  37. })
  38. if err != nil {
  39. return err
  40. }
  41. childPID = proc.Pid
  42. if _, err := proc.Wait(); err != nil {
  43. return err
  44. }
  45. return nil
  46. }
  47. // Restart the current binary without inheriting socket file descriptors. For
  48. // blank slate reinitialization, this is the best method to call. The parent
  49. // process environment, current working directory, command line arguments, and
  50. // STDIN, STDOUT, and STDERR are inherited by the child process.
  51. //
  52. // Consider using Router.Rebind() instead of Restart unless you need to listen
  53. // on different ports.
  54. //
  55. // Be aware that there appears to be a bug with fsnotify in that O_CLOEXEC on
  56. // its file descriptors isn't honored. You should consider closing any fsnotify
  57. // watchers that are active before this call if you don't want to leak
  58. // descriptors.
  59. //
  60. // This should be called from a goroutine. Parent/child process management is
  61. // not handled by this function.
  62. func Restart() error {
  63. cwd, _ := os.Getwd()
  64. exe, _ := os.Executable()
  65. proc, err := os.StartProcess(exe, os.Args, &os.ProcAttr{
  66. Dir: cwd,
  67. Env: os.Environ(),
  68. Files: []*os.File{
  69. os.Stdin,
  70. os.Stdout,
  71. os.Stderr,
  72. },
  73. })
  74. if err != nil {
  75. return err
  76. }
  77. if _, err := proc.Wait(); err != nil {
  78. return err
  79. }
  80. return nil
  81. }