posix_daemon_control_control.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //
  2. // $Id$
  3. //
  4. #include<__vic/posix/daemon_control.h>
  5. #include<__vic/ascii_string.h>
  6. #include<__vic/stdio_file.h>
  7. #include<__vic/error.h>
  8. #include<__vic/throw_errno.h>
  9. #include<__vic/string_buffer.h>
  10. #include<__vic/posix/process.h>
  11. #include<__vic/thread.h>
  12. #include<sys/types.h>
  13. #include<signal.h>
  14. #include<cstdio>
  15. #include<cerrno>
  16. namespace __vic { namespace posix {
  17. namespace {
  18. //----------------------------------------------------------------------------
  19. pid_t read_pid(const char *pid_file_name)
  20. {
  21. stdio_file file(pid_file_name, "r");
  22. if(!file.is_open()) return 0;
  23. unsigned pid;
  24. if(std::fscanf(file, "%u", &pid) != 1)
  25. throw exception("PID-file is broken");
  26. return pid;
  27. }
  28. //----------------------------------------------------------------------------
  29. void send_signal(pid_t pid, int signo)
  30. {
  31. if(::kill(pid, signo))
  32. switch(int err = errno)
  33. {
  34. case EPERM: throw exception("Insufficient privileges");
  35. case ESRCH: throw exception("No running process found");
  36. default: throw_errno("kill", err);
  37. }
  38. }
  39. //----------------------------------------------------------------------------
  40. void send_signal(const char *pid_file_name, int signo)
  41. {
  42. pid_t pid = read_pid(pid_file_name);
  43. if(pid == 0) throw exception("No running process found");
  44. send_signal(pid, signo);
  45. }
  46. //----------------------------------------------------------------------------
  47. } // namespace
  48. //----------------------------------------------------------------------------
  49. int daemon_control::control(const char *cmd, const char *pid_file_name)
  50. {
  51. if(ascii::equal_icase(cmd, "stop"))
  52. send_signal(pid_file_name, SIGTERM);
  53. else if(ascii::equal_icase(cmd, "kill"))
  54. send_signal(pid_file_name, SIGKILL);
  55. else if(ascii::equal_icase(cmd, "status")
  56. || ascii::equal_icase(cmd, "state"))
  57. {
  58. try
  59. {
  60. pid_t pid = read_pid(pid_file_name);
  61. if(pid != 0 && process_alive(pid))
  62. return (std::fputs("Running\n", stdout), 0);
  63. else
  64. return (std::fputs("Not running\n", stdout), 1);
  65. }
  66. catch(const std::exception &ex)
  67. {
  68. std::fprintf(stderr, "%s\n", ex.what());
  69. }
  70. return 2; // error
  71. }
  72. else throw exception(msg(64) << "Unknown command: \"" << cmd << '"');
  73. return 0;
  74. }
  75. //----------------------------------------------------------------------------
  76. void daemon_control::stop_and_wait(const char *pid_file_name)
  77. {
  78. pid_t pid = read_pid(pid_file_name);
  79. if(pid != 0) // process is running
  80. {
  81. send_signal(pid, SIGTERM); // stop the process
  82. while(::kill(pid, 0) == 0) // and wait for termination
  83. this_thread::sleep_ms(200);
  84. }
  85. }
  86. //----------------------------------------------------------------------------
  87. }} // namespace