mirror of
https://github.com/status-im/realm-js.git
synced 2025-01-11 14:54:33 +00:00
Fix bug due to std:🧵:id being reused
After a thread is destroyed, a thread id might be reused. This is true for pthread_self() and hence std:🧵:id. We were hitting this in Chrome debug mode because the "worker" thread was being destroyed and a new one immediately created when reloading. The thread id would be the same, and therefore we'd get back the SharedRealm for the previously destroyed thread (which had yet to be garbage collected. The new implementation uses an atomically incremented, thread-local identifier, which serves our needs very well. Fixes #473
This commit is contained in:
parent
7c2518c01f
commit
446cb0245e
@ -189,6 +189,7 @@
|
||||
F620F0571CB766DA0082977B /* node_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_init.cpp; sourceTree = "<group>"; };
|
||||
F620F0591CB7B4C80082977B /* js_object_accessor.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_object_accessor.hpp; sourceTree = "<group>"; };
|
||||
F620F0741CB9F60C0082977B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||
F6242B291D08EE9600BE1E03 /* thread_id.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = thread_id.hpp; sourceTree = "<group>"; };
|
||||
F6267BC91CADC30000AC36B1 /* js_util.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = js_util.hpp; sourceTree = "<group>"; };
|
||||
F6267BCA1CADC49200AC36B1 /* node_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_dummy.cpp; sourceTree = "<group>"; };
|
||||
F62BF8FB1CAC71780022BCDC /* libRealmNode.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libRealmNode.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -363,6 +364,7 @@
|
||||
02E008D11D10AB1B00F3AA37 /* atomic_shared_ptr.hpp */,
|
||||
02E008D21D10AB1B00F3AA37 /* format.cpp */,
|
||||
02E008D31D10AB1B00F3AA37 /* format.hpp */,
|
||||
F6242B291D08EE9600BE1E03 /* thread_id.hpp */,
|
||||
);
|
||||
name = util;
|
||||
path = src/util;
|
||||
|
@ -19,8 +19,9 @@
|
||||
#ifndef REALM_WEAK_REALM_NOTIFIER_BASE_HPP
|
||||
#define REALM_WEAK_REALM_NOTIFIER_BASE_HPP
|
||||
|
||||
#include "util/thread_id.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace realm {
|
||||
class Realm;
|
||||
@ -48,11 +49,11 @@ public:
|
||||
// Is this a WeakRealmNotifierBase for the given Realm instance?
|
||||
bool is_for_realm(Realm* realm) const { return realm == m_realm_key; }
|
||||
|
||||
bool is_for_current_thread() const { return m_thread_id == std::this_thread::get_id(); }
|
||||
bool is_for_current_thread() const { return m_thread_id == util::get_thread_id(); }
|
||||
|
||||
private:
|
||||
std::weak_ptr<Realm> m_realm;
|
||||
std::thread::id m_thread_id = std::this_thread::get_id();
|
||||
thread_id_t m_thread_id = util::get_thread_id();
|
||||
void* m_realm_key;
|
||||
bool m_cache = false;
|
||||
};
|
||||
|
@ -306,7 +306,7 @@ static void check_read_write(Realm *realm)
|
||||
|
||||
void Realm::verify_thread() const
|
||||
{
|
||||
if (m_thread_id != std::this_thread::get_id()) {
|
||||
if (m_thread_id != util::get_thread_id()) {
|
||||
throw IncorrectThreadException();
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,11 @@
|
||||
#ifndef REALM_REALM_HPP
|
||||
#define REALM_REALM_HPP
|
||||
|
||||
#include "util/thread_id.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace realm {
|
||||
@ -128,7 +130,7 @@ namespace realm {
|
||||
bool compact();
|
||||
void write_copy(StringData path, BinaryData encryption_key);
|
||||
|
||||
std::thread::id thread_id() const { return m_thread_id; }
|
||||
thread_id_t thread_id() const { return m_thread_id; }
|
||||
void verify_thread() const;
|
||||
void verify_in_write() const;
|
||||
|
||||
@ -174,7 +176,7 @@ namespace realm {
|
||||
|
||||
private:
|
||||
Config m_config;
|
||||
std::thread::id m_thread_id = std::this_thread::get_id();
|
||||
thread_id_t m_thread_id = util::get_thread_id();
|
||||
bool m_auto_refresh = true;
|
||||
|
||||
std::unique_ptr<Replication> m_history;
|
||||
|
@ -134,4 +134,4 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
#endif // REALM_ASYNC_QUERY_HPP
|
||||
#endif // REALM_ATOMIC_SHARED_PTR_HPP
|
||||
|
48
src/object-store/src/util/thread_id.hpp
Normal file
48
src/object-store/src/util/thread_id.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2016 Realm Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef REALM_THREAD_ID_HPP
|
||||
#define REALM_THREAD_ID_HPP
|
||||
|
||||
#include <realm/util/features.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace realm {
|
||||
|
||||
using thread_id_t = std::size_t;
|
||||
|
||||
namespace util {
|
||||
|
||||
// Since std::thread::id may be reused after a thread is destroyed, we use
|
||||
// an atomically incremented, thread-local identifier instead.
|
||||
inline thread_id_t get_thread_id() {
|
||||
static std::atomic<thread_id_t> id_counter;
|
||||
static REALM_THREAD_LOCAL thread_id_t thread_id = 0;
|
||||
|
||||
if (REALM_UNLIKELY(!thread_id)) {
|
||||
thread_id = ++id_counter;
|
||||
}
|
||||
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace realm
|
||||
|
||||
#endif // REALM_THREAD_ID_HPP
|
Loading…
x
Reference in New Issue
Block a user