daemons.cc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Copyright [2021] JD.com, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. #include <signal.h>
  18. #include <fcntl.h>
  19. #include <sys/poll.h>
  20. #include "daemons.h"
  21. #include "daemon/daemon.h"
  22. #include "log/log.h"
  23. extern int watchdog_stop;
  24. extern int load_all;
  25. extern int load_sharding;
  26. WatchDogPipe::WatchDogPipe()
  27. {
  28. int fd[2];
  29. int unused;
  30. unused = pipe(fd);
  31. netfd = fd[0];
  32. peerfd_ = fd[1];
  33. fcntl(netfd, F_SETFL, O_NONBLOCK);
  34. fcntl(peerfd_, F_SETFL, O_NONBLOCK);
  35. fcntl(netfd, F_SETFD, FD_CLOEXEC);
  36. fcntl(peerfd_, F_SETFD, FD_CLOEXEC);
  37. enable_input();
  38. }
  39. WatchDogPipe::~WatchDogPipe()
  40. {
  41. if (peerfd_ >= 0)
  42. close(peerfd_);
  43. }
  44. void WatchDogPipe::input_notify()
  45. {
  46. char buf[100];
  47. while (read(netfd, buf, sizeof(buf)) == sizeof(buf))
  48. ;
  49. }
  50. void WatchDogPipe::wake()
  51. {
  52. char c = 0;
  53. c = write(peerfd_, &c, 1);
  54. }
  55. static WatchDogPipe *notifier;
  56. static void sighdlr(int signo)
  57. {
  58. notifier->wake();
  59. }
  60. WatchDog::WatchDog()
  61. {
  62. /* 立马注册进程退出处理函数,解决启动时创建太多进程导致部分进程退出没有收到信号linjinming 2014-06-14*/
  63. notifier = new WatchDogPipe;
  64. //signal(SIGCHLD, sighdlr);
  65. struct sigaction sa;
  66. memset(&sa, 0, sizeof(sa));
  67. sa.sa_handler = sighdlr;
  68. sigaction(SIGCHLD, &sa, NULL);
  69. }
  70. WatchDog::~WatchDog(void)
  71. {
  72. }
  73. void close_sharding()
  74. {
  75. char* p[1];
  76. p[0] = NULL;
  77. execv("/usr/local/agent/sharding/bin/stop.sh", p);
  78. system("/usr/local/agent/sharding/bin/stop.sh");
  79. }
  80. void WatchDog::run_loop()
  81. {
  82. struct pollfd pfd[2];
  83. notifier->init_poll_fd(&pfd[0]);
  84. if (listener_) {
  85. listener_->init_poll_fd(&pfd[1]);
  86. } else {
  87. pfd[1].fd = -1;
  88. pfd[1].events = 0;
  89. pfd[1].revents = 0;
  90. }
  91. while (!watchdog_stop) {
  92. int timeout = expire_micro_seconds(1000, 1);
  93. //log4cplus_debug("befor poll, timeout:%d, %d, %d\n", timeout, pfd[0].fd, pfd[1].fd);
  94. int interrupted = poll(pfd, 2, timeout);
  95. //log4cplus_debug("after poll, watchdog_stop:%d, interrupted:%d\n", watchdog_stop, interrupted);
  96. update_now_time(timeout, interrupted);
  97. if (watchdog_stop)
  98. break;
  99. if (pfd[0].revents & POLLIN)
  100. notifier->input_notify();
  101. if (pfd[1].revents & POLLIN)
  102. listener_->input_notify();
  103. check_watchdog();
  104. check_expired();
  105. check_ready();
  106. }
  107. log4cplus_debug("prepare stopping");
  108. kill_allwatchdog();
  109. if(load_sharding || load_all)
  110. close_sharding();
  111. //force_kill_allwatchdog();
  112. check_watchdog();
  113. time_t stoptimer = time(NULL) + 5;
  114. int stopretry = 0;
  115. while (stopretry < 6 && get_process_count() > 0) {
  116. time_t now = time(NULL);
  117. if (stoptimer <= now) {
  118. stopretry++;
  119. stoptimer = now + 5;
  120. log4cplus_debug("notify all children again");
  121. kill_allwatchdog();
  122. }
  123. poll(pfd, 1, 1000);
  124. if (pfd[0].revents & POLLIN)
  125. notifier->input_notify();
  126. check_watchdog();
  127. }
  128. delete notifier;
  129. force_kill_allwatchdog();
  130. log4cplus_info("all children stopped, daemons ended");
  131. exit(0);
  132. }