Kea 3.1.1
interprocess_sync_file.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7// This file requires LOCKFILE_DIR to be defined. It points to the default
8// directory where lockfile will be created.
9
10#include <config.h>
11
13
14#include <string>
15#include <cerrno>
16#include <cstring>
17#include <sstream>
18#include <iostream>
19
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26
27namespace isc {
28namespace log {
29namespace interprocess {
30
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
40bool
41InterprocessSyncFile::do_lock(int cmd, short l_type) {
42 // Open lock file only when necessary (i.e., here). This is so that
43 // if a default InterprocessSync object is replaced with another
44 // implementation, it doesn't attempt any opens.
45 if (fd_ == -1) {
46 std::string lockfile_path = LOCKFILE_DIR;
47
48 const char* const env = getenv("KEA_LOCKFILE_DIR");
49 if (env != NULL) {
50 lockfile_path = env;
51 }
52
53 lockfile_path += "/" + task_name_ + "_lockfile";
54
55 // Open the lockfile in the constructor so it doesn't do the access
56 // checks every time a message is logged.
57 fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR,
58 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); // 0660
59 if (fd_ != -1) {
60 if (fchmod(fd_, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
61 close(fd_);
62 fd_ = -1;
63 }
64 }
65
66 if (fd_ == -1) {
67 std::stringstream tmp;
68
69 // We failed to create a lockfile. This means that the logging
70 // system is unusable. We need to report the issue using plain
71 // print to stderr.
72 tmp << "Unable to use interprocess sync lockfile ("
73 << std::strerror(errno) << "): " << lockfile_path;
74 std::cerr << tmp.str() << std::endl;
75
76 // And then throw exception as usual.
77 isc_throw(InterprocessSyncFileError, tmp.str());
78 }
79 }
80
81 struct flock lock;
82
83 memset(&lock, 0, sizeof (lock));
84 lock.l_type = l_type;
85 lock.l_whence = SEEK_SET;
86 lock.l_start = 0;
87 lock.l_len = 1;
88
89 return (fcntl(fd_, cmd, &lock) == 0);
90}
91
92bool
94 if (is_locked_) {
95 return (true);
96 }
97
98 if (do_lock(F_SETLKW, F_WRLCK)) {
99 is_locked_ = true;
100 return (true);
101 }
102
103 return (false);
104}
105
106bool
108 if (is_locked_) {
109 return (true);
110 }
111
112 if (do_lock(F_SETLK, F_WRLCK)) {
113 is_locked_ = true;
114 return (true);
115 }
116
117 return (false);
118}
119
120bool
122 if (!is_locked_) {
123 return (true);
124 }
125
126 if (do_lock(F_SETLKW, F_UNLCK)) {
127 is_locked_ = false;
128 return (true);
129 }
130
131 return (false);
132}
133
134} // namespace interprocess
135} // namespace log
136} // namespace isc
bool lock()
Acquire the lock (blocks if something else has acquired a lock on the same task name)
bool tryLock()
Try to acquire a lock (doesn't block)
const std::string task_name_
The task name.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.