skynet_daemon.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/file.h>
  5. #include <signal.h>
  6. #include <errno.h>
  7. #include <stdlib.h>
  8. #include <fcntl.h>
  9. #include "skynet_daemon.h"
  10. static int
  11. check_pid(const char *pidfile) {
  12. int pid = 0;
  13. FILE *f = fopen(pidfile,"r");
  14. if (f == NULL)
  15. return 0;
  16. int n = fscanf(f,"%d", &pid);
  17. fclose(f);
  18. if (n !=1 || pid == 0 || pid == getpid()) {
  19. return 0;
  20. }
  21. if (kill(pid, 0) && errno == ESRCH)
  22. return 0;
  23. return pid;
  24. }
  25. static int
  26. write_pid(const char *pidfile) {
  27. FILE *f;
  28. int pid = 0;
  29. int fd = open(pidfile, O_RDWR|O_CREAT, 0644);
  30. if (fd == -1) {
  31. fprintf(stderr, "Can't create pidfile [%s].\n", pidfile);
  32. return 0;
  33. }
  34. f = fdopen(fd, "w+");
  35. if (f == NULL) {
  36. fprintf(stderr, "Can't open pidfile [%s].\n", pidfile);
  37. return 0;
  38. }
  39. if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
  40. int n = fscanf(f, "%d", &pid);
  41. fclose(f);
  42. if (n != 1) {
  43. fprintf(stderr, "Can't lock and read pidfile.\n");
  44. } else {
  45. fprintf(stderr, "Can't lock pidfile, lock is held by pid %d.\n", pid);
  46. }
  47. return 0;
  48. }
  49. pid = getpid();
  50. if (!fprintf(f,"%d\n", pid)) {
  51. fprintf(stderr, "Can't write pid.\n");
  52. close(fd);
  53. return 0;
  54. }
  55. fflush(f);
  56. return pid;
  57. }
  58. static int
  59. redirect_fds() {
  60. int nfd = open("/dev/null", O_RDWR);
  61. if (nfd == -1) {
  62. perror("Unable to open /dev/null: ");
  63. return -1;
  64. }
  65. if (dup2(nfd, 0) < 0) {
  66. perror("Unable to dup2 stdin(0): ");
  67. return -1;
  68. }
  69. if (dup2(nfd, 1) < 0) {
  70. perror("Unable to dup2 stdout(1): ");
  71. return -1;
  72. }
  73. if (dup2(nfd, 2) < 0) {
  74. perror("Unable to dup2 stderr(2): ");
  75. return -1;
  76. }
  77. close(nfd);
  78. return 0;
  79. }
  80. int
  81. daemon_init(const char *pidfile) {
  82. int pid = check_pid(pidfile);
  83. if (pid) {
  84. fprintf(stderr, "Skynet is already running, pid = %d.\n", pid);
  85. return 1;
  86. }
  87. #ifdef __APPLE__
  88. fprintf(stderr, "'daemon' is deprecated: first deprecated in OS X 10.5 , use launchd instead.\n");
  89. #else
  90. if (daemon(1,1)) {
  91. fprintf(stderr, "Can't daemonize.\n");
  92. return 1;
  93. }
  94. #endif
  95. pid = write_pid(pidfile);
  96. if (pid == 0) {
  97. return 1;
  98. }
  99. if (redirect_fds()) {
  100. return 1;
  101. }
  102. return 0;
  103. }
  104. int
  105. daemon_exit(const char *pidfile) {
  106. return unlink(pidfile);
  107. }