interprocess_sync_file.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2012,2014 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. // This file requires LOCKFILE_DIR to be defined. It points to the default
  15. // directory where lockfile will be created.
  16. #include <log/interprocess/interprocess_sync_file.h>
  17. #include <string>
  18. #include <cerrno>
  19. #include <cstring>
  20. #include <sstream>
  21. #include <iostream>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. namespace isc {
  29. namespace log {
  30. namespace interprocess {
  31. InterprocessSyncFile::~InterprocessSyncFile() {
  32. if (fd_ != -1) {
  33. // This will also release any applied locks.
  34. close(fd_);
  35. // The lockfile will continue to exist, and we must not delete
  36. // it.
  37. }
  38. }
  39. bool
  40. InterprocessSyncFile::do_lock(int cmd, short l_type) {
  41. // Open lock file only when necessary (i.e., here). This is so that
  42. // if a default InterprocessSync object is replaced with another
  43. // implementation, it doesn't attempt any opens.
  44. if (fd_ == -1) {
  45. std::string lockfile_path = LOCKFILE_DIR;
  46. const char* const env = getenv("KEA_LOCKFILE_DIR");
  47. if (env != NULL) {
  48. lockfile_path = env;
  49. }
  50. lockfile_path += "/" + task_name_ + "_lockfile";
  51. // Open the lockfile in the constructor so it doesn't do the access
  52. // checks every time a message is logged.
  53. const mode_t mode = umask(S_IXUSR | S_IXGRP | S_IXOTH); // 0111
  54. fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR,
  55. S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); // 0660
  56. umask(mode);
  57. if (fd_ == -1) {
  58. std::stringstream tmp;
  59. // We failed to create a lockfile. This means that the logging
  60. // system is unusable. We need to report the issue using plain
  61. // print to stderr.
  62. tmp << "Unable to use interprocess sync lockfile ("
  63. << std::strerror(errno) << "): " << lockfile_path;
  64. std::cerr << tmp.str() << std::endl;
  65. // And then throw exception as usual.
  66. isc_throw(InterprocessSyncFileError, tmp.str());
  67. }
  68. }
  69. struct flock lock;
  70. memset(&lock, 0, sizeof (lock));
  71. lock.l_type = l_type;
  72. lock.l_whence = SEEK_SET;
  73. lock.l_start = 0;
  74. lock.l_len = 1;
  75. return (fcntl(fd_, cmd, &lock) == 0);
  76. }
  77. bool
  78. InterprocessSyncFile::lock() {
  79. if (is_locked_) {
  80. return (true);
  81. }
  82. if (do_lock(F_SETLKW, F_WRLCK)) {
  83. is_locked_ = true;
  84. return (true);
  85. }
  86. return (false);
  87. }
  88. bool
  89. InterprocessSyncFile::tryLock() {
  90. if (is_locked_) {
  91. return (true);
  92. }
  93. if (do_lock(F_SETLK, F_WRLCK)) {
  94. is_locked_ = true;
  95. return (true);
  96. }
  97. return (false);
  98. }
  99. bool
  100. InterprocessSyncFile::unlock() {
  101. if (!is_locked_) {
  102. return (true);
  103. }
  104. if (do_lock(F_SETLKW, F_UNLCK)) {
  105. is_locked_ = false;
  106. return (true);
  107. }
  108. return (false);
  109. }
  110. } // namespace interprocess
  111. } // namespace log
  112. } // namespace isc