• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-database / 41461446124

02 Nov 2026 02:23PM UTC coverage: 92.425% (+0.03%) from 92.4%
41461446124

push

github

web-flow
Merge pull request #1058 from evoskuil/master

Remove boost dependency.

53 of 55 new or added lines in 5 files covered. (96.36%)

2 existing lines in 2 files now uncovered.

9187 of 9940 relevant lines covered (92.42%)

821262.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.3
/src/locks/interprocess_lock.cpp
1
/**
2
 * Copyright (c) 2011-2026 libbitcoin developers
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/database/locks/interprocess_lock.hpp>
20

21
#include <filesystem>
22
#if !defined(HAVE_WINDOWS)
23
    #include <fcntl.h>
24
    #include <unistd.h>
25
#endif
26
#include <bitcoin/database/define.hpp>
27
#include <bitcoin/database/locks/file_lock.hpp>
28

29
namespace libbitcoin {
30
namespace database {
31

32
#if defined(HAVE_WINDOWS)
33
static void* const invalid = INVALID_HANDLE_VALUE;
34
#else
35
static constexpr int invalid = -1;
36
#endif
37

38
// Open the existing file and take an exclusive lock on its whole extent.
39
// Sharing allows the owner to delete the file before closing it.
40
static auto open_locked(const std::filesystem::path& file) NOEXCEPT
583 ✔
41
{
42
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
43
    const auto path = system::extended_path(file);
583 ✔
44
    BC_POP_WARNING()
45

46
#if defined(HAVE_WINDOWS)
47
    constexpr auto share = FILE_SHARE_READ | FILE_SHARE_WRITE |
48
        FILE_SHARE_DELETE;
49
    const auto handle = ::CreateFileW(path.c_str(), GENERIC_READ |
50
        GENERIC_WRITE, share, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
51
        nullptr);
52

53
    if (handle == invalid)
54
        return invalid;
55

56
    constexpr auto flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
57
    OVERLAPPED overlapped{};
58
    if (::LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped) ==
59
        FALSE)
60
    {
61
        ::CloseHandle(handle);
62
        return invalid;
63
    }
64

65
    return handle;
66
#else
67
    const auto descriptor = ::open(path.c_str(), O_RDWR);
68
    if (descriptor == invalid)
583 ✔
69
        return invalid;
70

71
    struct flock lock{};
583 ✔
72
    lock.l_type = F_WRLCK;
583 ✔
73
    lock.l_whence = SEEK_SET;
74
    if (::fcntl(descriptor, F_SETLK, &lock) == -1)
583 ✔
75
    {
NEW
76
        ::close(descriptor);
×
77
        return invalid;
78
    }
79

80
    return descriptor;
81
#endif
82
}
83

84
// Closing releases the lock.
85
template <typename Handle>
86
static void close_locked(Handle handle) NOEXCEPT
583 ✔
87
{
88
#if defined(HAVE_WINDOWS)
89
    ::CloseHandle(handle);
90
#else
91
    ::close(handle);
583 ✔
92
#endif
93
}
583 ✔
94

95
interprocess_lock::interprocess_lock(const std::filesystem::path& file) NOEXCEPT
610 ✔
96
  : file_lock(file), handle_(invalid)
610 ✔
97
{
98
}
610 ✔
99

100
interprocess_lock::~interprocess_lock() NOEXCEPT
610 ✔
101
{
102
    try_unlock();
610 ✔
103
}
610 ✔
104

105
// Lock is not idempotent, returns false if already locked (or error).
106
// This succeeds if no other process has exclusive or sharable ownership.
107
bool interprocess_lock::try_lock() NOEXCEPT
584 ✔
108
{
109
    // A valid handle guarantees file existence and ownership.
110
    if (handle_ != invalid)
584 ✔
111
        return false;
112

113
    // Create the file.
114
    if (!create())
583 ✔
115
        return false;
116

117
    // Obtain exclusive access to the file.
118
    handle_ = open_locked(file());
583 ✔
119
    return handle_ != invalid;
583 ✔
120
}
121

122
// Unlock is idempotent, returns true if unlocked on return (or success).
123
// This may leave the lock file behind, which is not a problem.
124
bool interprocess_lock::try_unlock() NOEXCEPT
725 ✔
125
{
126
    // An invalid handle guarantees lack of ownership, but file may exist.
127
    // Do not delete the file unless we own it.
128
    if (handle_ == invalid)
725 ✔
129
        return true;
130

131
    // Delete before close, to preclude delete of a file that is not owned,
132
    // resulting from a race condition. The file is queued for deletion.
133
    const auto result = destroy();
583 ✔
134

135
    // Release exclusive access to the file.
136
    close_locked(handle_);
583 ✔
137
    handle_ = invalid;
583 ✔
138
    return result;
583 ✔
139
}
140

141
} // namespace database
142
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc