process.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // SiYuan - Refactor your thinking
  2. // Copyright (c) 2020-present, b3log.org
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. package model
  17. import (
  18. "os"
  19. "os/signal"
  20. "strconv"
  21. "strings"
  22. "syscall"
  23. "time"
  24. goPS "github.com/mitchellh/go-ps"
  25. "github.com/siyuan-note/logging"
  26. "github.com/siyuan-note/siyuan/kernel/util"
  27. )
  28. func HandleSignal() {
  29. c := make(chan os.Signal)
  30. signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
  31. s := <-c
  32. logging.LogInfof("received os signal [%s], exit kernel process now", s)
  33. Close(false, true, 1)
  34. }
  35. var (
  36. firstRunHookDesktopUIProcJob = true
  37. )
  38. func HookDesktopUIProcJob() {
  39. if util.ContainerStd != util.Container || "dev" == util.Mode {
  40. return
  41. }
  42. if firstRunHookDesktopUIProcJob {
  43. // 等待启动结束再监控
  44. time.Sleep(30 * time.Second)
  45. firstRunHookDesktopUIProcJob = false
  46. return
  47. }
  48. if 0 < util.CountSessions() {
  49. // 如果存在活动的会话则说明 UI 进程还在运行
  50. return
  51. }
  52. uiProcCount := getAttachedUIProcCount()
  53. if 0 < uiProcCount {
  54. return
  55. }
  56. logging.LogWarnf("no active UI proc, continue to check from attached ui processes after 15s")
  57. time.Sleep(15 * time.Second)
  58. uiProcCount = getAttachedUIProcCount()
  59. if 0 < uiProcCount {
  60. return
  61. }
  62. logging.LogWarnf("no active UI proc, continue to check from all processes after 15s")
  63. time.Sleep(15 * time.Second)
  64. uiProcCount = getUIProcCount()
  65. if 0 < uiProcCount {
  66. logging.LogInfof("active UI proc count [%d]", uiProcCount)
  67. return
  68. }
  69. logging.LogWarnf("confirmed no active UI proc, exit kernel process now")
  70. Close(false, true, 1)
  71. }
  72. var uiProcNames = []string{"siyuan", "electron"}
  73. // getAttachedUIProcCount 获取已经附加的 UI 进程数。
  74. func getAttachedUIProcCount() (ret int) {
  75. util.UIProcessIDs.Range(func(uiProcIDArg, _ interface{}) bool {
  76. uiProcID, err := strconv.Atoi(uiProcIDArg.(string))
  77. if nil != err {
  78. logging.LogErrorf("invalid UI proc ID [%s]: %s", uiProcIDArg, err)
  79. return true
  80. }
  81. proc, err := goPS.FindProcess(uiProcID)
  82. if nil != err {
  83. logging.LogErrorf("find UI proc [%d] failed: %s", uiProcID, err)
  84. return true
  85. }
  86. if nil == proc {
  87. return true
  88. }
  89. procName := strings.ToLower(proc.Executable())
  90. uiProcOk := false
  91. for _, name := range uiProcNames {
  92. if uiProcOk = strings.Contains(procName, name); uiProcOk {
  93. break
  94. }
  95. }
  96. if uiProcOk {
  97. ret++
  98. }
  99. return true
  100. })
  101. return
  102. }
  103. // getUIProcCount 获取 UI 进程数。
  104. func getUIProcCount() (ret int) {
  105. pid := os.Getpid()
  106. procs, _ := goPS.Processes()
  107. for _, proc := range procs {
  108. if proc.Pid() == pid {
  109. continue
  110. }
  111. procName := strings.ToLower(proc.Executable())
  112. uiProcOk := false
  113. for _, name := range uiProcNames {
  114. if uiProcOk = strings.Contains(procName, name); uiProcOk {
  115. break
  116. }
  117. }
  118. if uiProcOk {
  119. ret++
  120. }
  121. }
  122. return
  123. }