Kea 3.1.8
interprocess_sync_file.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2026 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 <cerrno>
15#include <cstdlib>
16#include <cstring>
17#include <iostream>
18#include <sstream>
19#include <string>
20
21#include <fcntl.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
28namespace isc {
29namespace log {
30namespace interprocess {
31
33 if (fd_ != -1) {
34 // This will also release any applied locks.
35 close(fd_);
36 // The lockfile will continue to exist, and we must not delete
37 // it.
38 }
39}
40
41bool
42InterprocessSyncFile::do_lock(int cmd, short l_type) {
43 // Open lock file only when necessary (i.e., here). This is so that
44 // if a default InterprocessSync object is replaced with another
45 // implementation, it doesn't attempt any opens.
46 if (fd_ == -1) {
47 std::string lockfile_path = LOCKFILE_DIR;
48
49 const char* const env = getenv("KEA_LOCKFILE_DIR");
50 if (env != NULL) {
51 lockfile_path = env;
52 }
53
54 lockfile_path += "/" + task_name_ + "_lockfile";
55
56 // Open the lockfile in the constructor so it doesn't do the access
57 // checks every time a message is logged.
58 fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR,
59 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); // 0660
60 if (fd_ != -1) {
61 if (fchmod(fd_, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
62 close(fd_);
63 fd_ = -1;
64 }
65 }
66
67 if (fd_ == -1) {
68 std::stringstream tmp;
69
70 // We failed to create a lockfile. This means that the logging
71 // system is unusable. We need to report the issue using plain
72 // print to stderr.
73 tmp << "Unable to use interprocess sync lockfile ("
74 << std::strerror(errno) << "): " << lockfile_path;
75 std::cerr << tmp.str() << std::endl;
76
77 // And then throw exception as usual.
78 isc_throw(InterprocessSyncFileError, tmp.str());
79 }
80 }
81
82 struct flock lock;
83
84 memset(&lock, 0, sizeof (lock));
85 lock.l_type = l_type;
86 lock.l_whence = SEEK_SET;
87 lock.l_start = 0;
88 lock.l_len = 1;
89
90 return (fcntl(fd_, cmd, &lock) == 0);
91}
92
93bool
95 if (is_locked_) {
96 return (true);
97 }
98
99 if (do_lock(F_SETLKW, F_WRLCK)) {
100 is_locked_ = true;
101 return (true);
102 }
103
104 return (false);
105}
106
107bool
109 if (is_locked_) {
110 return (true);
111 }
112
113 if (do_lock(F_SETLK, F_WRLCK)) {
114 is_locked_ = true;
115 return (true);
116 }
117
118 return (false);
119}
120
121bool
123 if (!is_locked_) {
124 return (true);
125 }
126
127 if (do_lock(F_SETLKW, F_UNLCK)) {
128 is_locked_ = false;
129 return (true);
130 }
131
132 return (false);
133}
134
135} // namespace interprocess
136} // namespace log
137} // 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.