Skip to content

Commit e028cfd

Browse files
authored
Merge pull request #1530 from Tencent/dev
for v2.2.2
2 parents bd7a9f7 + 8093cb3 commit e028cfd

35 files changed

+137
-76
lines changed

Android/MMKV/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ org.gradle.jvmargs=-Xmx1536m
1414
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1515
# org.gradle.parallel=true
1616

17-
VERSION_NAME_PREFIX=2.2.1
17+
VERSION_NAME_PREFIX=2.2.2
1818
#VERSION_NAME_SUFFIX=-SNAPSHOT
1919
VERSION_NAME_SUFFIX=
2020

Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/BenchMarkBaseService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ private void mmkvBatchWriteInt(String caller) {
110110
for (int index = 0; index < m_loops; index++) {
111111
int tmp = r.nextInt();
112112
String key = m_arrIntKeys[index];
113+
// MMKV mmkv = MMKV.mmkvWithID(MMKV_ID + key, MMKV.MULTI_PROCESS_MODE, CryptKey);
113114
mmkv.encode(key, tmp);
114115
}
115116
long endTime = System.currentTimeMillis();

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
# MMKV Change Log
2+
## v2.2.2 / 2025-05-08
3+
This is a hot fix version mainly **for Android/Linux platforms**. It’s highly recommended for v2.2.0~v2.2.1 users.
4+
### Changes for All platforms
5+
* Improve file lock consistency for Mayfly FD MMKV instances.
6+
7+
### Android
8+
* Fix a potential ANR on multi-process mode MMKV init/creation.
9+
10+
### POSIX
11+
* Fix a potential ANR on multi-process mode MMKV init/creation on Linux.
12+
13+
### iOS/macOS
14+
* Retain the callback handler to prevent a potential short-lived callback handler from crashing.
15+
16+
### Win32
17+
* Improve efficiency on MMKV instance init/creation.
18+
219
## v2.2.1 / 2025-04-25
320
### Changes for All platforms
421
* Add `importFrom()`.

Core/InterProcessLock.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,12 @@ bool FileLock::unlock(LockType lockType) {
200200
return ret;
201201
}
202202

203-
void FileLock::destroyLock() {
204-
m_fd = MMKVFileHandleInvalidValue;
203+
void FileLock::destroyAndUnLock() {
204+
platformUnLock(false);
205205

206-
// m_sharedLockCount = 0;
207-
// m_exclusiveLockCount = 0;
206+
m_sharedLockCount = 0;
207+
m_exclusiveLockCount = 0;
208+
m_fd = MMKVFileHandleInvalidValue;
208209
}
209210

210211
} // namespace mmkv

Core/InterProcessLock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ class FileLock {
7878

7979
bool unlock(LockType lockType);
8080

81-
// the fd is invalid, destroy file lock
82-
void destroyLock();
81+
// unlock all and destroy file lock
82+
void destroyAndUnLock();
8383

8484
// just forbid it for possibly misuse
8585
explicit FileLock(const FileLock &other) = delete;

Core/MMKVPredef.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include <vector>
3535
#include <unordered_map>
3636

37-
constexpr auto MMKV_VERSION = "v2.2.1";
37+
constexpr auto MMKV_VERSION = "v2.2.2";
3838

3939
#ifdef DEBUG
4040
# define MMKV_DEBUG

Core/MemoryFile.cpp

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ MMKVFileHandle_t MemoryFile::getFd() {
158158
return m_diskFile.getFd();
159159
}
160160

161-
bool MemoryFile::truncate(size_t size) {
161+
bool MemoryFile::truncate(size_t size, FileLock *fileLock) {
162162
if (m_isMayflyFD) {
163163
openIfNeeded();
164164
}
@@ -218,7 +218,7 @@ bool MemoryFile::truncate(size_t size) {
218218
MMKVError("fail to munmap [%s], %s", m_diskFile.m_path.c_str(), strerror(errno));
219219
}
220220
}
221-
return mmapOrCleanup();
221+
return mmapOrCleanup(fileLock);
222222
}
223223

224224
bool MemoryFile::msync(SyncFlag syncFlag) {
@@ -236,7 +236,7 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
236236
return false;
237237
}
238238

239-
bool MemoryFile::mmapOrCleanup() {
239+
bool MemoryFile::mmapOrCleanup(FileLock *fileLock) {
240240
auto oldPtr = m_ptr;
241241
auto mode = m_readOnly ? PROT_READ : (PROT_READ | PROT_WRITE);
242242
m_ptr = (char *) ::mmap(m_ptr, m_size, mode, MAP_SHARED, m_diskFile.m_fd, 0);
@@ -249,6 +249,10 @@ bool MemoryFile::mmapOrCleanup() {
249249
}
250250
MMKVInfo("mmap to address [%p], oldPtr [%p], [%s]", m_ptr, oldPtr, m_diskFile.m_path.c_str());
251251

252+
if (m_isMayflyFD && fileLock) {
253+
fileLock->destroyAndUnLock();
254+
}
255+
252256
cleanMayflyFD();
253257
return true;
254258
}
@@ -279,17 +283,9 @@ void MemoryFile::reloadFromFile(size_t expectedCapacity) {
279283

280284
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;;
281285
roundSize = std::max<size_t>(expectedSize, roundSize);
282-
truncate(roundSize);
283-
284-
if (m_isMayflyFD) {
285-
fileLock.destroyLock();
286-
}
286+
truncate(roundSize, &fileLock);
287287
} else {
288-
mmapOrCleanup();
289-
290-
if (m_isMayflyFD) {
291-
fileLock.destroyLock();
292-
}
288+
mmapOrCleanup(&fileLock);
293289
}
294290
# ifdef MMKV_IOS
295291
if (!m_readOnly) {

Core/MemoryFile.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ T roundUp(T numToRound, T multiple) {
6868
return ((numToRound + multiple - 1) / multiple) * multiple;
6969
}
7070

71+
class FileLock;
72+
7173
class File {
7274
MMKVPath_t m_path;
7375
MMKVFileHandle_t m_fd;
@@ -119,7 +121,7 @@ class MemoryFile {
119121
const bool m_readOnly;
120122
const bool m_isMayflyFD;
121123

122-
bool mmapOrCleanup();
124+
bool mmapOrCleanup(FileLock *fileLock);
123125

124126
void doCleanMemoryCache(bool forceClean);
125127

@@ -151,7 +153,7 @@ class MemoryFile {
151153
void cleanMayflyFD();
152154

153155
// the newly expanded file content will be zeroed
154-
bool truncate(size_t size);
156+
bool truncate(size_t size, FileLock *fileLock = nullptr);
155157

156158
bool msync(SyncFlag syncFlag);
157159

Core/MemoryFile_Android.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ MemoryFile::MemoryFile(string path, size_t size, FileType fileType, size_t expec
7878
} else {
7979
if (m_diskFile.isFileValid()) {
8080
m_size = m_diskFile.m_size;
81-
mmapOrCleanup();
81+
mmapOrCleanup(nullptr);
8282
}
8383
}
8484
}
@@ -91,7 +91,7 @@ MemoryFile::MemoryFile(int ashmemFD)
9191
} else {
9292
m_size = m_diskFile.m_size;
9393
MMKVInfo("ashmem name:%s, size:%zu", m_diskFile.m_path.c_str(), m_size);
94-
mmapOrCleanup();
94+
mmapOrCleanup(nullptr);
9595
}
9696
}
9797

Core/MemoryFile_Win32.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ MemoryFile::MemoryFile(MMKVPath_t path, size_t expectedCapacity, bool readOnly,
111111
reloadFromFile(expectedCapacity);
112112
}
113113

114-
bool MemoryFile::truncate(size_t size) {
114+
bool MemoryFile::truncate(size_t size, FileLock *fileLock) {
115115
if (m_isMayflyFD) {
116116
openIfNeeded();
117117
}
@@ -152,7 +152,7 @@ bool MemoryFile::truncate(size_t size) {
152152
MMKVError("fail to truncate [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
153153
m_size = oldSize;
154154
if (needMMapOnFailure) {
155-
mmapOrCleanup();
155+
mmapOrCleanup(fileLock);
156156
}
157157
return false;
158158
}
@@ -161,13 +161,13 @@ bool MemoryFile::truncate(size_t size) {
161161
MMKVError("fail to zeroFile [%ls] to size %zu", m_diskFile.m_path.c_str(), m_size);
162162
m_size = oldSize;
163163
if (needMMapOnFailure) {
164-
mmapOrCleanup();
164+
mmapOrCleanup(fileLock);
165165
}
166166
return false;
167167
}
168168
}
169169

170-
return mmapOrCleanup();
170+
return mmapOrCleanup(fileLock);
171171
}
172172

173173
bool MemoryFile::msync(SyncFlag syncFlag) {
@@ -193,7 +193,7 @@ bool MemoryFile::msync(SyncFlag syncFlag) {
193193
return false;
194194
}
195195

196-
bool MemoryFile::mmapOrCleanup() {
196+
bool MemoryFile::mmapOrCleanup(FileLock *fileLock) {
197197
auto mode = m_readOnly ? PAGE_READONLY : PAGE_READWRITE;
198198
m_fileMapping = CreateFileMapping(m_diskFile.getFd(), nullptr, mode, 0, 0, nullptr);
199199
if (!m_fileMapping) {
@@ -210,6 +210,10 @@ bool MemoryFile::mmapOrCleanup() {
210210
}
211211
MMKVInfo("mmap to address [%p], [%ls]", m_ptr, m_diskFile.m_path.c_str());
212212

213+
if (m_isMayflyFD && fileLock) {
214+
fileLock->destroyAndUnLock();
215+
}
216+
213217
cleanMayflyFD();
214218
return true;
215219
}
@@ -223,26 +227,21 @@ void MemoryFile::reloadFromFile(size_t expectedCapacity) {
223227
}
224228
if (openIfNeeded()) {
225229
FileLock fileLock(m_diskFile.getFd());
226-
InterProcessLock lock(&fileLock, ExclusiveLockType);
230+
InterProcessLock lock(&fileLock, SharedLockType);
227231
SCOPED_LOCK(&lock);
228232

229233
mmkv::getFileSize(m_diskFile.getFd(), m_size);
230234
size_t expectedSize = std::max<size_t>(DEFAULT_MMAP_SIZE, roundUp<size_t>(expectedCapacity, DEFAULT_MMAP_SIZE));
231235
// round up to (n * pagesize)
232236
if (!m_readOnly && (m_size < expectedSize || (m_size % DEFAULT_MMAP_SIZE != 0))) {
237+
InterProcessLock exclusiveLock(&fileLock, ExclusiveLockType);
238+
SCOPED_LOCK(&exclusiveLock);
239+
233240
size_t roundSize = ((m_size / DEFAULT_MMAP_SIZE) + 1) * DEFAULT_MMAP_SIZE;;
234241
roundSize = std::max<size_t>(expectedSize, roundSize);
235-
truncate(roundSize);
236-
237-
if (m_isMayflyFD) {
238-
fileLock.destroyLock();
239-
}
242+
truncate(roundSize, &fileLock);
240243
} else {
241-
mmapOrCleanup();
242-
243-
if (m_isMayflyFD) {
244-
fileLock.destroyLock();
245-
}
244+
mmapOrCleanup(&fileLock);
246245
}
247246
}
248247
}

MMKV.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "MMKV"
4-
s.version = "2.2.1"
4+
s.version = "2.2.2"
55
s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat."
66

77
s.description = <<-DESC
@@ -33,7 +33,7 @@ Pod::Spec.new do |s|
3333
"CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF" => "NO",
3434
}
3535

36-
s.dependency 'MMKVCore', '~> 2.2.1'
36+
s.dependency 'MMKVCore', '~> 2.2.2'
3737

3838
end
3939

MMKVAppExtension.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "MMKVAppExtension"
4-
s.version = "2.2.1"
4+
s.version = "2.2.2"
55
s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat."
66
s.module_name = "MMKVAppExtension"
77

@@ -31,7 +31,7 @@ Pod::Spec.new do |s|
3131
"GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION",
3232
}
3333

34-
s.dependency 'MMKVCore', '~> 2.2.1'
34+
s.dependency 'MMKVCore', '~> 2.2.2'
3535

3636
end
3737

MMKVCore.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "MMKVCore"
4-
s.version = "2.2.1"
4+
s.version = "2.2.2"
55
s.summary = "MMKVCore for MMKV. MMKV is a cross-platform key-value storage framework developed by WeChat."
66

77
s.description = <<-DESC

MMKVWatchExtension.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22

33
s.name = "MMKVWatchExtension"
4-
s.version = "2.2.1"
4+
s.version = "2.2.2"
55
s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat."
66
s.module_name = "MMKVWatchExtension"
77

@@ -31,7 +31,7 @@ Pod::Spec.new do |s|
3131
"GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION",
3232
}
3333

34-
s.dependency 'MMKVCore', '~> 2.2.1'
34+
s.dependency 'MMKVCore', '~> 2.2.2'
3535

3636
end
3737

OpenHarmony/MMKV/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# MMKV for HarmonyOS NEXT Change Log
2+
## v2.2.2 / 2025-05-08
3+
This is a hot fix version mainly **for Android/Linux platforms**. It’s highly recommended for v2.2.0~v2.2.1 users.
4+
* Improve file lock consistency for Mayfly FD MMKV instances.
5+
26
## v2.2.1 / 2025-04-25
37
* Add `importFrom()`.
48

OpenHarmony/MMKV/oh-package.json5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tencent/mmkv",
3-
"version": "2.2.1",
3+
"version": "2.2.2",
44
"description": "The official OpenHarmony package of MMKV. An efficient, small mobile key-value storage framework developed by WeChat.",
55
"main": "Index.ets",
66
"author": "guoling",

POSIX/demo/TestInterProcessLock.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <sys/stat.h>
2727
#include <unistd.h>
2828
#include <cstring>
29+
#include <sys/mman.h>
2930

3031
// it's not a must-have for most app so do it the handy way
3132
#include "../../Core/InterProcessLock.h"
@@ -108,6 +109,19 @@ int main() {
108109

109110
auto processID = getpid();
110111
cout << "TestInterProcessLock: " << processID << " started\n";
112+
113+
// auto fd3 = open("/tmp/mmkv/TestInterProcessLock2.file", O_RDWR | O_CREAT | O_CLOEXEC, S_IRWXU);
114+
// FileLock flock3(fd3);
115+
//
116+
// auto ptr = ::mmap(nullptr, DEFAULT_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd3, 0);
117+
// printf("mmap fd %d to %p\n", fd3, ptr);
118+
//
119+
// printf("trying flock.try_lock %d\n", fd3);
120+
// flock3.try_lock(ExclusiveLockType, nullptr);
121+
// printf("trying flock.lock %d\n", fd3);
122+
// flock3.lock(ExclusiveLockType);
123+
// printf("finish flock.lock %d\n", fd3);
124+
111125
auto ret = threadTest();
112126
cout << "TestInterProcessLock: " << (ret ? "pass" : "failed") << endl;
113127
cout << "TestInterProcessLock: " << processID << " ended\n";

POSIX/demo/demo.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <ctime>
3737
#include <cmath>
3838
#include <cinttypes> // For PRId64 & PRIu64
39+
#include <sys/mman.h>
3940

4041
// it's not a must-have for most app so do it the handy way
4142
#include "../../Core/InterProcessLock.h"
@@ -311,6 +312,14 @@ void testInterProcessLock() {
311312
auto fd = open("/tmp/mmkv/TestInterProcessLock.file", O_RDWR | O_CREAT | O_CLOEXEC, S_IRWXU);
312313
FileLock flock(fd);
313314

315+
// auto fd2 = open("/tmp/mmkv/TestInterProcessLock2.file", O_RDWR | O_CREAT | O_CLOEXEC, S_IRWXU);
316+
// FileLock flock2(fd2);
317+
// flock2.lock(SharedLockType);
318+
// auto ptr = ::mmap(nullptr, DEFAULT_MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
319+
// printf("mmap fd %d to %p\n", fd2, ptr);
320+
// ::close(fd2);
321+
// flock2.destroyLock();
322+
314323
auto pid = fork();
315324
// this is child
316325
if (pid <= 0) {

0 commit comments

Comments
 (0)