diff --git a/Android/MMKV/build.gradle b/Android/MMKV/build.gradle index b7ba6d80..f6b5ef58 100644 --- a/Android/MMKV/build.gradle +++ b/Android/MMKV/build.gradle @@ -8,7 +8,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.1' + classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.1' classpath 'digital.wup:android-maven-publish:3.6.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/Android/MMKV/gradle.properties b/Android/MMKV/gradle.properties index 7999f8c8..5c6a19db 100644 --- a/Android/MMKV/gradle.properties +++ b/Android/MMKV/gradle.properties @@ -14,6 +14,6 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -VERSION_NAME_PREFIX=1.2.2 +VERSION_NAME_PREFIX=1.2.3 #VERSION_NAME_SUFFIX=-SNAPSHOT VERSION_NAME_SUFFIX= \ No newline at end of file diff --git a/Android/MMKV/gradle/wrapper/gradle-wrapper.properties b/Android/MMKV/gradle/wrapper/gradle-wrapper.properties index 70fb7485..8887d393 100644 --- a/Android/MMKV/gradle/wrapper/gradle-wrapper.properties +++ b/Android/MMKV/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jun 02 16:48:00 CST 2020 +#Fri Oct 16 21:16:39 CST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/Android/MMKV/mmkv/build.gradle b/Android/MMKV/mmkv/build.gradle index 43672b7a..c3f83731 100644 --- a/Android/MMKV/mmkv/build.gradle +++ b/Android/MMKV/mmkv/build.gradle @@ -68,6 +68,6 @@ dependencies { implementation 'androidx.annotation:annotation:1.1.0' javadocDeps 'androidx.annotation:annotation:1.1.0' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' } diff --git a/Android/MMKV/mmkvdemo/build.gradle b/Android/MMKV/mmkvdemo/build.gradle index 0114e1d1..b0a6d4fa 100644 --- a/Android/MMKV/mmkvdemo/build.gradle +++ b/Android/MMKV/mmkvdemo/build.gradle @@ -82,13 +82,13 @@ repositories { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation project(':mmkv') -// implementation 'com.tencent:mmkv:1.2.2' -// implementation 'com.tencent:mmkv-static:1.2.2' - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' +// implementation 'com.tencent:mmkv:1.2.3' +// implementation 'com.tencent:mmkv-static:1.2.3' + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + androidTestImplementation 'androidx.test:runner:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.getkeepsafe.relinker:relinker:1.3.1' } diff --git a/CHANGELOG.md b/CHANGELOG.md index 25c2c06a..1116f0e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # MMKV Change Log +## v1.2.3 / 2020-10-16 +### Changes for All platforms +* Fix a potential crash on 32-bit devices due to pointer alignment issue. +* Fix a decode error of encrypted MMKV on some 32-bit devices. + +### iOS / macOS +* Fix a potential `crc32()` crash on some kind of arm64 devices. +* Fix a potential crash after calling `+[MMKV onAppTerminate]`. + +### Android +* Fix a rare lock conflict on `checkProcessMode()`. + +### POSIX +Add MMKV support for **Python** on POSIX platforms. Most things actually work! +Check out the [wiki](https://github.com/Tencent/MMKV/wiki/python_setup) for more info. + ## v1.2.2 / 2020-07-30 ### iOS / macOS diff --git a/Core/CodedInputDataCrypt.cpp b/Core/CodedInputDataCrypt.cpp index 4578e92a..02e26365 100644 --- a/Core/CodedInputDataCrypt.cpp +++ b/Core/CodedInputDataCrypt.cpp @@ -19,6 +19,7 @@ */ #include "CodedInputDataCrypt.h" +#include "MMKVLog.h" #include "PBUtility.h" #include #include diff --git a/Core/InterProcessLock.cpp b/Core/InterProcessLock.cpp index 7db7228f..6fb5d34e 100644 --- a/Core/InterProcessLock.cpp +++ b/Core/InterProcessLock.cpp @@ -31,11 +31,11 @@ bool FileLock::lock(LockType lockType) { return doLock(lockType, true); } -bool FileLock::try_lock(LockType lockType) { - return doLock(lockType, false); +bool FileLock::try_lock(LockType lockType, bool *tryAgain) { + return doLock(lockType, false, tryAgain); } -bool FileLock::doLock(LockType lockType, bool wait) { +bool FileLock::doLock(LockType lockType, bool wait, bool *tryAgain) { if (!isFileLockValid()) { return false; } @@ -59,7 +59,7 @@ bool FileLock::doLock(LockType lockType, bool wait) { } } - auto ret = platformLock(lockType, wait, unLockFirstIfNeeded); + auto ret = platformLock(lockType, wait, unLockFirstIfNeeded, tryAgain); if (ret) { if (lockType == SharedLockType) { m_sharedLockCount++; @@ -82,10 +82,10 @@ static int32_t LockType2FlockType(LockType lockType) { return LOCK_EX; } -bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded) { +bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded, bool *tryAgain) { # ifdef MMKV_ANDROID if (m_isAshmem) { - return ashmemLock(lockType, wait, unLockFirstIfNeeded); + return ashmemLock(lockType, wait, unLockFirstIfNeeded, tryAgain); } # endif auto realLockType = LockType2FlockType(lockType); @@ -105,7 +105,12 @@ bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeed auto ret = flock(m_fd, cmd); if (ret != 0) { - MMKVError("fail to lock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + if (tryAgain) { + *tryAgain = (errno == EWOULDBLOCK); + } + if (wait) { + MMKVError("fail to lock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); + } // try recover my shared-lock if (unLockFirstIfNeeded) { ret = flock(m_fd, LockType2FlockType(SharedLockType)); diff --git a/Core/InterProcessLock.h b/Core/InterProcessLock.h index 2da539b0..32b3b1db 100644 --- a/Core/InterProcessLock.h +++ b/Core/InterProcessLock.h @@ -22,9 +22,9 @@ #define MMKV_INTERPROCESSLOCK_H #ifdef __cplusplus -#include "MMKVPredef.h" +# include "MMKVPredef.h" -#include +# include namespace mmkv { @@ -40,39 +40,39 @@ class FileLock { size_t m_sharedLockCount; size_t m_exclusiveLockCount; - bool doLock(LockType lockType, bool wait); - bool platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded); + bool doLock(LockType lockType, bool wait, bool *tryAgain = nullptr); + bool platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded, bool *tryAgain); bool platformUnLock(bool unLockFirstIfNeeded); -#ifndef MMKV_WIN32 +# ifndef MMKV_WIN32 bool isFileLockValid() { return m_fd >= 0; } -# ifdef MMKV_ANDROID +# ifdef MMKV_ANDROID const bool m_isAshmem; struct flock m_lockInfo; - bool ashmemLock(LockType lockType, bool wait, bool unLockFirstIfNeeded); + bool ashmemLock(LockType lockType, bool wait, bool unLockFirstIfNeeded, bool *tryAgain); bool ashmemUnLock(bool unLockFirstIfNeeded); -# endif +# endif -#else // defined(MMKV_WIN32) +# else // defined(MMKV_WIN32) OVERLAPPED m_overLapped; bool isFileLockValid() { return m_fd != INVALID_HANDLE_VALUE; } -#endif // MMKV_WIN32 +# endif // MMKV_WIN32 public: -#ifndef MMKV_WIN32 -# ifndef MMKV_ANDROID +# ifndef MMKV_WIN32 +# ifndef MMKV_ANDROID explicit FileLock(MMKVFileHandle_t fd) : m_fd(fd), m_sharedLockCount(0), m_exclusiveLockCount(0) {} -# else +# else explicit FileLock(MMKVFileHandle_t fd, bool isAshmem = false); -# endif // MMKV_ANDROID -#else // defined(MMKV_WIN32) +# endif // MMKV_ANDROID +# else // defined(MMKV_WIN32) explicit FileLock(MMKVFileHandle_t fd) : m_fd(fd), m_overLapped{}, m_sharedLockCount(0), m_exclusiveLockCount(0) {} -#endif // MMKV_WIN32 +# endif // MMKV_WIN32 bool lock(LockType lockType); - bool try_lock(LockType lockType); + bool try_lock(LockType lockType, bool *tryAgain); bool unlock(LockType lockType); @@ -99,9 +99,9 @@ class InterProcessLock { } } - bool try_lock() { + bool try_lock(bool *tryAgain = nullptr) { if (m_enable) { - return m_fileLock->try_lock(m_lockType); + return m_fileLock->try_lock(m_lockType, tryAgain); } return false; } @@ -115,5 +115,5 @@ class InterProcessLock { } // namespace mmkv -#endif -#endif //MMKV_INTERPROCESSLOCK_H +#endif // __cplusplus +#endif // MMKV_INTERPROCESSLOCK_H diff --git a/Core/InterProcessLock_Android.cpp b/Core/InterProcessLock_Android.cpp index 9eab6096..12247f89 100644 --- a/Core/InterProcessLock_Android.cpp +++ b/Core/InterProcessLock_Android.cpp @@ -45,7 +45,7 @@ static short LockType2FlockType(LockType lockType) { } } -bool FileLock::ashmemLock(LockType lockType, bool wait, bool unLockFirstIfNeeded) { +bool FileLock::ashmemLock(LockType lockType, bool wait, bool unLockFirstIfNeeded, bool *tryAgain) { m_lockInfo.l_type = LockType2FlockType(lockType); if (unLockFirstIfNeeded) { // try lock @@ -66,6 +66,9 @@ bool FileLock::ashmemLock(LockType lockType, bool wait, bool unLockFirstIfNeeded int cmd = wait ? F_SETLKW : F_SETLK; auto ret = fcntl(m_fd, cmd, &m_lockInfo); if (ret != 0) { + if (tryAgain) { + *tryAgain = (errno == EAGAIN); + } if (wait) { MMKVError("fail to lock fd=%d, ret=%d, error:%s", m_fd, ret, strerror(errno)); } diff --git a/Core/InterProcessLock_Win32.cpp b/Core/InterProcessLock_Win32.cpp index fe2c619b..bbc31ce8 100644 --- a/Core/InterProcessLock_Win32.cpp +++ b/Core/InterProcessLock_Win32.cpp @@ -38,7 +38,7 @@ static DWORD LockType2Flag(LockType lockType) { return flag; } -bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded) { +bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeeded, bool *tryAgain) { auto realLockType = LockType2Flag(lockType); auto flag = wait ? realLockType : (realLockType | LOCKFILE_FAIL_IMMEDIATELY); if (unLockFirstIfNeeded) { @@ -56,7 +56,12 @@ bool FileLock::platformLock(LockType lockType, bool wait, bool unLockFirstIfNeed auto ret = LockFileEx(m_fd, flag, 0, 1, 0, &m_overLapped); if (!ret) { - MMKVError("fail to lock fd=%p, error:%d", m_fd, GetLastError()); + if (tryAgain) { + *tryAgain = (GetLastError() == ERROR_LOCK_VIOLATION); + } + if (wait) { + MMKVError("fail to lock fd=%p, error:%d", m_fd, GetLastError()); + } // try recover my shared-lock if (unLockFirstIfNeeded) { ret = LockFileEx(m_fd, LockType2Flag(SharedLockType), 0, 1, 0, &m_overLapped); diff --git a/Core/KeyValueHolder.cpp b/Core/KeyValueHolder.cpp index 9694348c..6bb5ab4a 100644 --- a/Core/KeyValueHolder.cpp +++ b/Core/KeyValueHolder.cpp @@ -111,9 +111,21 @@ KeyValueHolderCrypt::~KeyValueHolderCrypt() { } } +uint32_t KeyValueHolderCrypt::realValueSize() const { + switch (type) { + case KeyValueHolderType_Direct: + return paddedSize; + case KeyValueHolderType_Offset: + return valueSize; + case KeyValueHolderType_Memory: + return memSize; + } + return 0; +} + // get decrypt data with [position, -1) static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &inputBuffer, size_t position) { - static uint8_t smallBuffer[16]; + static size_t smallBuffer[16 / sizeof(size_t)]; auto basePtr = (uint8_t *) inputBuffer.getPtr(); auto ptr = basePtr; for (size_t index = sizeof(smallBuffer); index < position; index += sizeof(smallBuffer)) { diff --git a/Core/KeyValueHolder.h b/Core/KeyValueHolder.h index 355ee890..6051581f 100644 --- a/Core/KeyValueHolder.h +++ b/Core/KeyValueHolder.h @@ -91,6 +91,8 @@ struct KeyValueHolderCrypt { ~KeyValueHolderCrypt(); + uint32_t realValueSize() const; + MMBuffer toMMBuffer(const void *basePtr, const AESCrypt *crypter) const; std::tuple toTuple() { diff --git a/Core/MMKV.cpp b/Core/MMKV.cpp index d6ec4164..75a28aab 100644 --- a/Core/MMKV.cpp +++ b/Core/MMKV.cpp @@ -135,6 +135,8 @@ MMKV::~MMKV() { delete m_sharedProcessModeLock; delete m_exclusiveProcessModeLock; #endif + + MMKVInfo("destruct [%s]", m_mmapID.c_str()); } MMKV *MMKV::defaultMMKV(MMKVMode mode, string *cryptKey) { @@ -163,12 +165,16 @@ void initialize() { AES_encrypt = openssl_aes_armv8_encrypt; AES_decrypt = openssl_aes_armv8_decrypt; MMKVInfo("armv8 AES instructions is supported"); + } else { + MMKVInfo("armv8 AES instructions is not supported"); } # endif // MMKV_DISABLE_CRYPT # ifdef MMKV_USE_ARMV8_CRC32 if (hwcaps & HWCAP_CRC32) { CRC32 = mmkv::armv8_crc32; MMKVInfo("armv8 CRC32 instructions is supported"); + } else { + MMKVInfo("armv8 CRC32 instructions is not supported"); } # endif // MMKV_USE_ARMV8_CRC32 #endif // __aarch64__ && defined(__linux__) diff --git a/Core/MMKV_Android.cpp b/Core/MMKV_Android.cpp index 57400e12..16e76e0a 100644 --- a/Core/MMKV_Android.cpp +++ b/Core/MMKV_Android.cpp @@ -59,8 +59,9 @@ MMKV::MMKV(const string &mmapID, int size, MMKVMode mode, string *cryptKey, stri m_actualSize = 0; m_output = nullptr; - m_fileModeLock = nullptr; - m_sharedProcessModeLock = nullptr; + // force use fcntl(), otherwise will conflict with MemoryFile::reloadFromFile() + m_fileModeLock = new FileLock(m_file->getFd(), true); + m_sharedProcessModeLock = new InterProcessLock(m_fileModeLock, SharedLockType); m_exclusiveProcessModeLock = nullptr; # ifndef MMKV_DISABLE_CRYPT @@ -107,8 +108,9 @@ MMKV::MMKV(const string &mmapID, int ashmemFD, int ashmemMetaFD, string *cryptKe m_actualSize = 0; m_output = nullptr; - m_fileModeLock = nullptr; - m_sharedProcessModeLock = nullptr; + // force use fcntl(), otherwise will conflict with MemoryFile::reloadFromFile() + m_fileModeLock = new FileLock(m_file->getFd(), true); + m_sharedProcessModeLock = new InterProcessLock(m_fileModeLock, SharedLockType); m_exclusiveProcessModeLock = nullptr; # ifndef MMKV_DISABLE_CRYPT @@ -213,35 +215,48 @@ bool MMKV::checkProcessMode() { return true; } - if (!m_fileModeLock) { - // force use fcntl(), otherwise will conflict with MemoryFile::reloadFromFile() - m_fileModeLock = new FileLock(m_file->getFd(), true); - } - if (!m_sharedProcessModeLock) { - m_sharedProcessModeLock = new InterProcessLock(m_fileModeLock, SharedLockType); - } if (m_isInterProcess) { if (!m_exclusiveProcessModeLock) { m_exclusiveProcessModeLock = new InterProcessLock(m_fileModeLock, ExclusiveLockType); } + // avoid multiple processes get shared lock at the same time, https://github.com/Tencent/MMKV/issues/523 + auto tryAgain = false; + auto exclusiveLocked = m_exclusiveProcessModeLock->try_lock(&tryAgain); + if (exclusiveLocked) { + return true; + } auto shareLocked = m_sharedProcessModeLock->try_lock(); if (!shareLocked) { // this call will fail on most case, just do it to make sure m_exclusiveProcessModeLock->try_lock(); return true; } else { - auto exclusiveLocked = m_exclusiveProcessModeLock->try_lock(); + if (!tryAgain) { + // something wrong with the OS/filesystem, let's try again + exclusiveLocked = m_exclusiveProcessModeLock->try_lock(&tryAgain); + if (!exclusiveLocked && !tryAgain) { + // still something wrong, we have to give up and assume it passed the test + MMKVWarning("Got a shared lock, but fail to exclusive lock [%s], assume it's ok", m_mmapID.c_str()); + exclusiveLocked = true; + } + } if (!exclusiveLocked) { - MMKVError("Fail to exclusive lock [%s]", m_mmapID.c_str()); + MMKVError("Got a shared lock, but fail to exclusive lock [%s]", m_mmapID.c_str()); } return exclusiveLocked; } } else { - auto ret = m_sharedProcessModeLock->try_lock(); - if (!ret) { + auto tryAgain = false; + auto shareLocked = m_sharedProcessModeLock->try_lock(&tryAgain); + if (!shareLocked && !tryAgain) { + // something wrong with the OS/filesystem, we have to give up and assume it passed the test + MMKVWarning("Fail to shared lock [%s], assume it's ok", m_mmapID.c_str()); + shareLocked = true; + } + if (!shareLocked) { MMKVError("Fail to share lock [%s]", m_mmapID.c_str()); } - return ret; + return shareLocked; } } diff --git a/Core/MMKV_IO.cpp b/Core/MMKV_IO.cpp index 9f937733..6318e45f 100644 --- a/Core/MMKV_IO.cpp +++ b/Core/MMKV_IO.cpp @@ -35,8 +35,8 @@ #include "aes/openssl/openssl_md5.h" #include "crc32/Checksum.h" #include -#include #include +#include #ifdef MMKV_IOS # include "MMKV_OSX.h" diff --git a/Core/MMKV_OSX.cpp b/Core/MMKV_OSX.cpp index 3130b098..e9f1e110 100644 --- a/Core/MMKV_OSX.cpp +++ b/Core/MMKV_OSX.cpp @@ -56,6 +56,40 @@ extern MMKVPath_t g_rootDir; enum { UnKnown = 0, PowerMac = 1, Mac, iPhone, iPod, iPad, AppleTV, AppleWatch }; static void GetAppleMachineInfo(int &device, int &version); +# ifdef MMKV_USE_ARMV8_CRC32 +# include +# include + +static sigjmp_buf g_jmpBuff; + +static void TrivialSignalHandler(int signo) { + siglongjmp(g_jmpBuff, 1); +} + +__attribute__((target("crc"))) static bool DetectCRCAvailabilityBySIGILL() { + volatile auto result = true; + + volatile auto oldHandler = signal(SIGILL, TrivialSignalHandler); + if (oldHandler == SIG_ERR) { + return false; + } + + if (sigsetjmp(g_jmpBuff, 1)) { + result = false; + } else { + auto tmp = __builtin_arm_crc32d(0, 1); + tmp = __builtin_arm_crc32w(tmp, 2); + tmp = __builtin_arm_crc32h(tmp, 3); + tmp = __builtin_arm_crc32b(tmp, 4); + + result = !!tmp; + } + + signal(SIGILL, oldHandler); + return result; +} +# endif // MMKV_USE_ARMV8_CRC32 + MMKV_NAMESPACE_BEGIN # ifdef MMKV_IOS @@ -99,9 +133,14 @@ void MMKV::minimalInit(MMKVPath_t defaultRootDir) { GetAppleMachineInfo(device, version); # ifdef MMKV_USE_ARMV8_CRC32 if ((device == iPhone && version >= 9) || (device == iPad && version >= 7)) { - CRC32 = mmkv::armv8_crc32; + // it's reported that some 64-bit iPhone (7 and above) doesn't support CRC32: https://github.com/Tencent/MMKV/issues/525 + // try to detect by signal handler + if (DetectCRCAvailabilityBySIGILL()) { + CRC32 = mmkv::armv8_crc32; + MMKVInfo("Detect CRC Availability By SIGILL: Looks like armv8 CRC32 instructions are supported"); + } } -# endif +# endif // MMKV_USE_ARMV8_CRC32 MMKVInfo("Apple Device:%d, version:%d", device, version); g_rootDir = defaultRootDir; diff --git a/Core/MemoryFile_Win32.cpp b/Core/MemoryFile_Win32.cpp index 29f0597b..32b44ea2 100644 --- a/Core/MemoryFile_Win32.cpp +++ b/Core/MemoryFile_Win32.cpp @@ -27,6 +27,7 @@ # include "MMKVLog.h" # include "ScopedLock.hpp" # include "ThreadLock.h" +# include using namespace std; diff --git a/Core/MiniPBCoder.cpp b/Core/MiniPBCoder.cpp index 8c88523e..51b0a837 100644 --- a/Core/MiniPBCoder.cpp +++ b/Core/MiniPBCoder.cpp @@ -301,7 +301,7 @@ void MiniPBCoder::decodeOneMap(MMKVMapCrypt &dic, size_t position, bool greedy) const auto &key = m_inputDataDecrpt->readString(kvHolder); if (key.length() > 0) { m_inputDataDecrpt->readData(kvHolder); - if (kvHolder.valueSize > 0) { + if (kvHolder.realValueSize() > 0) { dictionary[key] = move(kvHolder); } else { auto itr = dictionary.find(key); diff --git a/Core/crc32/Checksum.h b/Core/crc32/Checksum.h index 6d87e4ee..81d3f821 100644 --- a/Core/crc32/Checksum.h +++ b/Core/crc32/Checksum.h @@ -54,7 +54,7 @@ extern CRC32_Func_t CRC32; #else // MMKV_EMBED_ZLIB -# ifdef __aarch64__ +# if defined(__aarch64__) && !defined(MMKV_APPLE) # define MMKV_USE_ARMV8_CRC32 @@ -66,7 +66,7 @@ uint32_t armv8_crc32(uint32_t crc, const uint8_t *buf, size_t len); typedef uint32_t (*CRC32_Func_t)(uint32_t crc, const uint8_t *buf, size_t len); extern CRC32_Func_t CRC32; -# else // __aarch64__ +# else // defined(__aarch64__) && !defined(MMKV_APPLE) # include diff --git a/MMKV.podspec b/MMKV.podspec index 33439169..e88d2260 100644 --- a/MMKV.podspec +++ b/MMKV.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKV" - s.version = "1.2.2" + s.version = "1.2.3" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.description = <<-DESC @@ -30,7 +30,7 @@ Pod::Spec.new do |s| "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF" => "NO", } - s.dependency 'MMKVCore', '~> 1.2.2' + s.dependency 'MMKVCore', '~> 1.2.3' end diff --git a/MMKVAppExtension.podspec b/MMKVAppExtension.podspec index 2e6e5843..fa819f6a 100644 --- a/MMKVAppExtension.podspec +++ b/MMKVAppExtension.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVAppExtension" - s.version = "1.2.2" + s.version = "1.2.3" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.module_name = "MMKVAppExtension" @@ -31,7 +31,7 @@ Pod::Spec.new do |s| "GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION", } - s.dependency 'MMKVCore', '~> 1.2.2' + s.dependency 'MMKVCore', '~> 1.2.3' end diff --git a/MMKVCore.podspec b/MMKVCore.podspec index c61df9b3..a02644ca 100644 --- a/MMKVCore.podspec +++ b/MMKVCore.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVCore" - s.version = "1.2.2" + s.version = "1.2.3" s.summary = "MMKVCore for MMKV. MMKV is a cross-platform key-value storage framework developed by WeChat." s.description = <<-DESC diff --git a/MMKVWatchExtension.podspec b/MMKVWatchExtension.podspec index 26db32d0..4153b448 100644 --- a/MMKVWatchExtension.podspec +++ b/MMKVWatchExtension.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MMKVWatchExtension" - s.version = "1.2.2" + s.version = "1.2.3" s.summary = "MMKV is a cross-platform key-value storage framework developed by WeChat." s.module_name = "MMKVWatchExtension" @@ -31,7 +31,7 @@ Pod::Spec.new do |s| "GCC_PREPROCESSOR_DEFINITIONS" => "MMKV_IOS_EXTENSION", } - s.dependency 'MMKVCore', '~> 1.2.2' + s.dependency 'MMKVCore', '~> 1.2.3' end diff --git a/POSIX/demo/UnitTest.cpp b/POSIX/demo/UnitTest.cpp index be1e7cf6..e9924f6b 100644 --- a/POSIX/demo/UnitTest.cpp +++ b/POSIX/demo/UnitTest.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include diff --git a/README.md b/README.md index f6a25896..05a258ce 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![license](https://img.shields.io/badge/license-BSD_3-brightgreen.svg?style=flat)](https://github.com/Tencent/MMKV/blob/master/LICENSE.TXT) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/MMKV/pulls) -[![Release Version](https://img.shields.io/badge/release-1.2.2-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) +[![Release Version](https://img.shields.io/badge/release-1.2.3-brightgreen.svg)](https://github.com/Tencent/MMKV/releases) [![Platform](https://img.shields.io/badge/Platform-%20Android%20%7C%20iOS%2FmacOS%20%7C%20Win32%20%7C%20POSIX-brightgreen.svg)](https://github.com/Tencent/MMKV/wiki/home) 中文版本请参看[这里](./readme_cn.md) @@ -28,8 +28,8 @@ Add the following lines to `build.gradle` on your app module: ```gradle dependencies { - implementation 'com.tencent:mmkv-static:1.2.2' - // replace "1.2.2" with any available version + implementation 'com.tencent:mmkv-static:1.2.3' + // replace "1.2.3" with any available version } ``` diff --git a/iOS/MMKV/MMKV.xcodeproj/project.pbxproj b/iOS/MMKV/MMKV.xcodeproj/project.pbxproj index 8dea9339..a722a6bf 100644 --- a/iOS/MMKV/MMKV.xcodeproj/project.pbxproj +++ b/iOS/MMKV/MMKV.xcodeproj/project.pbxproj @@ -485,7 +485,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -531,7 +531,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -742,7 +742,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -782,7 +782,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -829,7 +829,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, @@ -878,7 +878,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACOSX_DEPLOYMENT_TARGET = 10.9; - MARKETING_VERSION = 1.2.2; + MARKETING_VERSION = 1.2.3; "OTHER_LDFLAGS[sdk=iphoneos*]" = ( "-framework", UIKit, diff --git a/iOS/MMKV/MMKV/libMMKV.mm b/iOS/MMKV/MMKV/libMMKV.mm index 82c401f5..536578d5 100644 --- a/iOS/MMKV/MMKV/libMMKV.mm +++ b/iOS/MMKV/MMKV/libMMKV.mm @@ -225,7 +225,9 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + MMKVInfo("dealloc %@", m_mmapID); [m_mmapID release]; + if (m_mmkv) { m_mmkv->close(); m_mmkv = nullptr; @@ -517,6 +519,10 @@ - (void)checkContentChanged { + (void)onAppTerminate { g_lock->lock(); + // make sure no further call will go into m_mmkv + [g_instanceDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, MMKV *_Nonnull mmkv, BOOL *_Nonnull stop) { + mmkv->m_mmkv = nullptr; + }]; [g_instanceDic release]; g_instanceDic = nil; diff --git a/readme_cn.md b/readme_cn.md index c61683bc..4e94462d 100644 --- a/readme_cn.md +++ b/readme_cn.md @@ -22,8 +22,8 @@ MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列 ```gradle dependencies { - implementation 'com.tencent:mmkv-static:1.2.2' - // replace "1.2.2" with any available version + implementation 'com.tencent:mmkv-static:1.2.3' + // replace "1.2.3" with any available version } ```