interprocess_sync_file.cc 3.3 KB

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