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

realm / realm-core / github_pull_request_312964

19 Feb 2025 07:31PM UTC coverage: 90.814% (-0.3%) from 91.119%
github_pull_request_312964

Pull #8071

Evergreen

web-flow
Bump serialize-javascript and mocha

Bumps [serialize-javascript](https://github.com/yahoo/serialize-javascript) to 6.0.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `serialize-javascript` from 6.0.0 to 6.0.2
- [Release notes](https://github.com/yahoo/serialize-javascript/releases)
- [Commits](https://github.com/yahoo/serialize-javascript/compare/v6.0.0...v6.0.2)

Updates `mocha` from 10.2.0 to 10.8.2
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v10.2.0...v10.8.2)

---
updated-dependencies:
- dependency-name: serialize-javascript
  dependency-type: indirect
- dependency-name: mocha
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #8071: Bump serialize-javascript and mocha

96552 of 179126 branches covered (53.9%)

212672 of 234185 relevant lines covered (90.81%)

3115802.0 hits per line

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

44.52
/src/realm/util/thread.cpp
1
/*************************************************************************
2
 *
3
 * Copyright 2016 Realm Inc.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 **************************************************************************/
18

19
#include <realm/util/thread.hpp>
20
#include <realm/util/backtrace.hpp>
21

22
#include <cstring>
23
#include <stdexcept>
24
#include <system_error>
25

26
#if !defined _WIN32
27
#include <unistd.h>
28
#endif
29

30
// "Process shared mutexes" are not officially supported on Android,
31
// but they appear to work anyway.
32
#if (defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED > 0) || REALM_ANDROID
33
#define REALM_HAVE_PTHREAD_PROCESS_SHARED
34
#endif
35

36
// Unfortunately Older Ubuntu releases such as 10.04 reports support
37
// for robust mutexes by setting _POSIX_THREADS = 200809L and
38
// _POSIX_THREAD_PROCESS_SHARED = 200809L even though they do not
39
// provide pthread_mutex_consistent(). See also
40
// http://www.gnu.org/software/gnulib/manual/gnulib.html#pthread_005fmutex_005fconsistent.
41
// Support was added to glibc 2.12, so we disable for earlier versions
42
// of glibs
43
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
44
#if !defined _WIN32 // 'robust' not supported by our windows pthreads port
45
#if _POSIX_THREADS >= 200809L
46
#ifdef __GNU_LIBRARY__
47
#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12 && !REALM_ANDROID
48
#define REALM_HAVE_ROBUST_PTHREAD_MUTEX
49
#endif
50
#elif !REALM_ANDROID
51
#define REALM_HAVE_ROBUST_PTHREAD_MUTEX
52
#endif
53
#endif
54
#endif
55
#endif
56

57

58
using namespace realm;
59
using namespace realm::util;
60

61
void Thread::set_name(const std::string& name)
62
{
96✔
63
#if REALM_PLATFORM_APPLE
64
    int r = pthread_setname_np(name.data());
65
    if (REALM_UNLIKELY(r != 0))
66
        throw std::system_error(r, std::system_category(), "pthread_setname_np() failed");
67
#elif REALM_HAVE_PTHREAD_SETNAME || (!defined(REALM_HAVE_PTHREAD_SETNAME) && defined(_GNU_SOURCE))
68
// Look for the HAVE_ macro defined by CMake. If building outside CMake and the macro wasn't explicitly defined, fall
69
// back to assuming this is available on Unix-y systems.
70
#if defined(__linux__)
71
    // Thread names on Linux can only be 16 characters long, including the null terminator
72
    const size_t max = 16;
73
    size_t n = name.size();
74
    if (n > max - 1)
75
        n = max - 1;
76
    char name_2[max];
77
    std::copy(name.data(), name.data() + n, name_2);
78
    name_2[n] = '\0';
79
#else
80
    const char* name_2 = name.c_str();
81
#endif
82
    pthread_t id = pthread_self();
83
    int r = pthread_setname_np(id, name_2);
84
    if (REALM_UNLIKELY(r != 0))
85
        throw std::system_error(r, std::system_category(), "pthread_setname_np() failed");
86
#else
87
    static_cast<void>(name);
96✔
88
#endif
96✔
89
}
96✔
90

91

92
bool Thread::get_name(std::string& name) noexcept
93
{
783✔
94
// Look for the HAVE_ macro defined by CMake. If building outside CMake and the macro wasn't explicitly defined, fall
95
// back to assuming this is available on Unix-y systems.
96
#if REALM_HAVE_PTHREAD_GETNAME ||                                                                                    \
97
    (!defined(REALM_HAVE_PTHREAD_GETNAME) && (defined(_GNU_SOURCE) || REALM_PLATFORM_APPLE))
98
    const size_t max = 64;
99
    char name_2[max];
100
    pthread_t id = pthread_self();
101
    int r = pthread_getname_np(id, name_2, max);
102
    if (REALM_UNLIKELY(r != 0)) {
103
        return false;
104
    }
105
    name_2[max - 1] = '\0';              // Eliminate any risk of buffer overrun in strlen().
106
    name.assign(name_2, strlen(name_2)); // Throws
107
    return true;
108
#else
109
    static_cast<void>(name);
783✔
110
    return false;
783✔
111
#endif
783✔
112
}
783✔
113

114

115
void Mutex::init_as_process_shared(bool robust_if_available)
116
{
104,823✔
117
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
104,823✔
118
    pthread_mutexattr_t attr;
104,823✔
119
    int r = pthread_mutexattr_init(&attr);
104,823✔
120
    if (REALM_UNLIKELY(r != 0))
104,823✔
121
        attr_init_failed(r);
×
122
    r = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
104,823✔
123
    REALM_ASSERT(r == 0);
104,823✔
124
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
104,823✔
125
    if (robust_if_available) {
104,823✔
126
        r = pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
104,823✔
127
        REALM_ASSERT(r == 0);
104,823✔
128
    }
104,823✔
129
#else // !REALM_HAVE_ROBUST_PTHREAD_MUTEX
130
    static_cast<void>(robust_if_available);
131
#endif
132
    r = pthread_mutex_init(&m_impl, &attr);
104,823✔
133
    int r2 = pthread_mutexattr_destroy(&attr);
104,823✔
134
    REALM_ASSERT(r2 == 0);
104,823✔
135
    if (REALM_UNLIKELY(r != 0))
104,823✔
136
        init_failed(r);
×
137
#else // !REALM_HAVE_PTHREAD_PROCESS_SHARED
138
    static_cast<void>(robust_if_available);
139
    throw util::runtime_error("No support for process-shared mutexes");
140
#endif
141
}
104,823✔
142

143
REALM_NORETURN void Mutex::init_failed(int err)
144
{
×
145
    switch (err) {
×
146
        case ENOMEM:
×
147
            throw util::bad_alloc();
×
148
        default:
×
149
            throw std::system_error(err, std::system_category(), "pthread_mutex_init() failed");
×
150
    }
×
151
}
×
152

153
REALM_NORETURN void Mutex::attr_init_failed(int err)
154
{
×
155
    switch (err) {
×
156
        case ENOMEM:
×
157
            throw util::bad_alloc();
×
158
        default:
×
159
            throw std::system_error(err, std::system_category(), "pthread_mutexattr_init() failed");
×
160
    }
×
161
}
×
162

163
REALM_NORETURN void Mutex::destroy_failed(int err) noexcept
164
{
×
165
    if (err == EBUSY)
×
166
        REALM_TERMINATE("Destruction of mutex in use");
167
    REALM_TERMINATE("pthread_mutex_destroy() failed");
168
}
×
169

170

171
REALM_NORETURN void Mutex::lock_failed(int err) noexcept
172
{
×
173
    switch (err) {
×
174
        case EDEADLK:
×
175
            REALM_TERMINATE("pthread_mutex_lock() failed: Recursive locking of mutex (deadlock)");
176
        case EINVAL:
×
177
            REALM_TERMINATE("pthread_mutex_lock() failed: Invalid mutex object provided");
178
        case EAGAIN:
×
179
            REALM_TERMINATE("pthread_mutex_lock() failed: Maximum number of recursive locks exceeded");
180
        default:
×
181
            REALM_TERMINATE("pthread_mutex_lock() failed");
182
    }
×
183
}
×
184

185

186
bool RobustMutex::low_level_lock()
187
{
3,634,719✔
188
#ifdef _WIN32
189
    REALM_ASSERT_RELEASE(false);
190
#else
191
    int r = pthread_mutex_lock(&m_impl);
3,634,719✔
192
    if (REALM_LIKELY(r == 0))
3,634,719✔
193
        return true;
3,646,995✔
194
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
2,147,483,647✔
195
    if (r == EOWNERDEAD)
2,147,483,647✔
196
        return false;
×
197
    if (r == ENOTRECOVERABLE)
2,147,483,647✔
198
        throw NotRecoverable();
×
199
#endif
2,147,483,647✔
200
    lock_failed(r);
2,147,483,647✔
201
#endif // _WIN32
2,147,483,647✔
202
}
2,147,483,647✔
203

204
int RobustMutex::try_low_level_lock()
205
{
60✔
206
#ifdef _WIN32
207
    REALM_ASSERT_RELEASE(false);
208
#else
209
    int r = pthread_mutex_trylock(&m_impl);
60✔
210
    if (REALM_LIKELY(r == 0))
60✔
211
        return 1;
45✔
212
    if (r == EBUSY)
15✔
213
        return 0;
15✔
214
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
×
215
    if (r == EOWNERDEAD)
×
216
        return -1;
×
217
    if (r == ENOTRECOVERABLE)
×
218
        throw NotRecoverable();
×
219
#endif
×
220
    lock_failed(r);
×
221
#endif // _WIN32
×
222
}
×
223

224
bool RobustMutex::is_valid() noexcept
225
{
36,345✔
226
#ifdef _WIN32
227
    REALM_ASSERT_RELEASE(false);
228
#else
229
    // FIXME: This check tries to lock the mutex, and only unlocks it if the
230
    // return value is zero. If pthread_mutex_trylock() fails with EOWNERDEAD,
231
    // this leads to deadlock during the following propper attempt to lock. This
232
    // cannot be fixed by also unlocking on failure with EOWNERDEAD, because
233
    // that would mark the mutex as consistent again and prevent the expected
234
    // notification.
235
    int r = pthread_mutex_trylock(&m_impl);
36,345✔
236
    if (r == 0) {
36,345✔
237
        r = pthread_mutex_unlock(&m_impl);
34,758✔
238
        REALM_ASSERT(r == 0);
34,758✔
239
        return true;
34,758✔
240
    }
34,758✔
241
    return r != EINVAL;
1,587✔
242
#endif
36,345✔
243
}
36,345✔
244

245

246
void RobustMutex::mark_as_consistent() noexcept
247
{
×
248
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
×
249
    int r = pthread_mutex_consistent(&m_impl);
×
250
    REALM_ASSERT(r == 0);
×
251
#endif
×
252
}
×
253

254

255
CondVar::CondVar(process_shared_tag)
256
{
69,885✔
257
#ifdef REALM_HAVE_PTHREAD_PROCESS_SHARED
69,885✔
258
    pthread_condattr_t attr;
69,885✔
259
    int r = pthread_condattr_init(&attr);
69,885✔
260
    if (REALM_UNLIKELY(r != 0))
69,885✔
261
        attr_init_failed(r);
×
262
    r = pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
69,885✔
263
    REALM_ASSERT(r == 0);
69,885✔
264
    r = pthread_cond_init(&m_impl, &attr);
69,885✔
265
    int r2 = pthread_condattr_destroy(&attr);
69,885✔
266
    REALM_ASSERT(r2 == 0);
69,885✔
267
    if (REALM_UNLIKELY(r != 0))
69,885✔
268
        init_failed(r);
×
269
#else
270
    throw util::runtime_error("No support for process-shared condition variables");
271
#endif
272
}
69,885✔
273

274
REALM_NORETURN void CondVar::init_failed(int err)
275
{
×
276
    switch (err) {
×
277
        case ENOMEM:
×
278
            throw util::bad_alloc();
×
279
        default:
×
280
            throw std::system_error(err, std::system_category(), "pthread_cond_init() failed");
×
281
    }
×
282
}
×
283

284
void CondVar::handle_wait_error(int err)
285
{
×
286
    switch (err) {
×
287
#ifdef REALM_HAVE_ROBUST_PTHREAD_MUTEX
×
288
        case ENOTRECOVERABLE:
×
289
            throw RobustMutex::NotRecoverable();
×
290
        case EOWNERDEAD:
×
291
            return;
×
292
#endif
×
293
        case EINVAL:
×
294
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed: Invalid argument provided");
295
        case EPERM:
×
296
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed:"
297
                            "Mutex not owned by calling thread");
×
298
        default:
×
299
            REALM_TERMINATE("pthread_cond_wait()/pthread_cond_timedwait() failed");
300
    }
×
301
}
×
302

303
REALM_NORETURN void CondVar::attr_init_failed(int err)
304
{
×
305
    switch (err) {
×
306
        case ENOMEM:
×
307
            throw util::bad_alloc();
×
308
        default:
×
309
            throw std::system_error(err, std::system_category(), "pthread_condattr_init() failed");
×
310
    }
×
311
}
×
312

313
REALM_NORETURN void CondVar::destroy_failed(int err) noexcept
314
{
×
315
    if (err == EBUSY)
×
316
        REALM_TERMINATE("Destruction of condition variable in use");
317
    REALM_TERMINATE("pthread_cond_destroy() failed");
318
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc