interprocess_sync_file.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright (C) 2012 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. #include "interprocess_sync_file.h"
  15. #include <string>
  16. #include <cerrno>
  17. #include <cstring>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. namespace isc {
  25. namespace util {
  26. InterprocessSyncFile::~InterprocessSyncFile() {
  27. if (fd_ != -1) {
  28. // This will also release any applied locks.
  29. close(fd_);
  30. // The lockfile will continue to exist, and we must not delete
  31. // it.
  32. }
  33. }
  34. bool
  35. InterprocessSyncFile::do_lock(int cmd, short l_type) {
  36. // Open lock file only when necessary (i.e., here). This is so that
  37. // if a default InterprocessSync object is replaced with another
  38. // implementation, it doesn't attempt any opens.
  39. if (fd_ == -1) {
  40. std::string lockfile_path = LOCKFILE_DIR;
  41. const char* const env = getenv("B10_FROM_BUILD");
  42. if (env != NULL) {
  43. lockfile_path = env;
  44. }
  45. const char* const env2 = getenv("B10_FROM_BUILD_LOCALSTATEDIR");
  46. if (env2 != NULL) {
  47. lockfile_path = env2;
  48. }
  49. const char* const env3 = getenv("B10_LOCKFILE_DIR_FROM_BUILD");
  50. if (env3 != NULL) {
  51. lockfile_path = env3;
  52. }
  53. lockfile_path += "/" + task_name_ + "_lockfile";
  54. // Open the lockfile in the constructor so it doesn't do the access
  55. // checks every time a message is logged.
  56. const mode_t mode = umask(0111);
  57. fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR, 0660);
  58. umask(mode);
  59. if (fd_ == -1) {
  60. isc_throw(InterprocessSyncFileError,
  61. "Unable to use interprocess sync lockfile ("
  62. << std::strerror(errno) << "): " << lockfile_path);
  63. }
  64. }
  65. struct flock lock;
  66. memset(&lock, 0, sizeof (lock));
  67. lock.l_type = l_type;
  68. lock.l_whence = SEEK_SET;
  69. lock.l_start = 0;
  70. lock.l_len = 1;
  71. return (fcntl(fd_, cmd, &lock) == 0);
  72. }
  73. bool
  74. InterprocessSyncFile::lock() {
  75. if (is_locked_) {
  76. return (true);
  77. }
  78. if (do_lock(F_SETLKW, F_WRLCK)) {
  79. is_locked_ = true;
  80. return (true);
  81. }
  82. return (false);
  83. }
  84. bool
  85. InterprocessSyncFile::tryLock() {
  86. if (is_locked_) {
  87. return (true);
  88. }
  89. if (do_lock(F_SETLK, F_WRLCK)) {
  90. is_locked_ = true;
  91. return (true);
  92. }
  93. return (false);
  94. }
  95. bool
  96. InterprocessSyncFile::unlock() {
  97. if (!is_locked_) {
  98. return (true);
  99. }
  100. if (do_lock(F_SETLKW, F_UNLCK)) {
  101. is_locked_ = false;
  102. return (true);
  103. }
  104. return (false);
  105. }
  106. } // namespace util
  107. } // namespace isc