diff --git a/CHANGELOG.md b/CHANGELOG.md index 082bd689299..744b00341f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Fix all UBSan failures hit by tests. It is unclear if any of these manifested as visible bugs. ([PR #5665](https://github.com/realm/realm-core/pull/5665)) * Fix sorting order for `realm_query_find_first` in the C API.([#5720](https://github.com/realm/realm-core/issues/5720)) * Upload completion callbacks may have called before the download message that completed them was fully integrated. ([#4865](https://github.com/realm/realm-core/issues/4865)). +* Fixed an exception "fcntl() with F_BARRIERFSYNC failed: Inappropriate ioctl for device" when running with MacOS on an exFAT drive. ([#5789](https://github.com/realm/realm-core/issues/5789) since 12.0.0) * Syncing of a Decimal128 with big significand could result in a crash. ([#5728](https://github.com/realm/realm-core/issues/5728)) diff --git a/evergreen/config.yml b/evergreen/config.yml index a9c29c2fc0b..b1319003691 100644 --- a/evergreen/config.yml +++ b/evergreen/config.yml @@ -369,6 +369,17 @@ tasks: xcrun swift build xcrun swift run ObjectStoreTests +- name: test-on-exfat + commands: + - func: "fetch source" + - func: "fetch binaries" + - func: "compile" + - command: shell.exec + params: + working_dir: realm-core/build + shell: /bin/bash + script: ../tools/run-tests-on-exfat.sh + - name: bloaty commands: - func: "fetch source" @@ -899,6 +910,7 @@ buildvariants: - name: benchmarks - name: long-running-tests - name: swift-build-and-test + - name: test-on-exfat - name: macos-1100-arm64 display_name: "MacOS 11 arm64" diff --git a/src/realm/util/file.cpp b/src/realm/util/file.cpp index c1fa6b36991..122a2c14c48 100644 --- a/src/realm/util/file.cpp +++ b/src/realm/util/file.cpp @@ -1044,10 +1044,10 @@ void File::barrier() #if REALM_PLATFORM_APPLE if (::fcntl(m_fd, F_BARRIERFSYNC) == 0) return; - throw std::system_error(errno, std::system_category(), "fcntl() with F_BARRIERFSYNC failed"); -#else - sync(); + // If fcntl fails, we fallback to full sync. + // This is known to occur on exFAT which does not support F_BARRIERSYNC. #endif + sync(); } #ifndef _WIN32 diff --git a/test/test_all.cpp b/test/test_all.cpp index a3e1a5a7173..c92a670de46 100644 --- a/test/test_all.cpp +++ b/test/test_all.cpp @@ -545,7 +545,7 @@ bool run_tests(util::Logger* logger) } // anonymous namespace -int test_all(util::Logger* logger, bool disable_all_sync_to_disk) +int test_all(util::Logger* logger) { // General note: Some Github clients on Windows will interfere with the .realm files created by unit tests (the // git client will attempt to access the files when it sees that new files have been created). This may cause @@ -563,7 +563,8 @@ int test_all(util::Logger* logger, bool disable_all_sync_to_disk) // e.g. due to power off. // NOTE: This is not strictly true. If encryption is enabled, a crash of the testsuite // (not the whole platform) may produce corrupt realm files. - if (disable_all_sync_to_disk) + char* enable_sync_to_disk = getenv("UNITTEST_ENABLE_SYNC_TO_DISK"); + if (!enable_sync_to_disk) disable_sync_to_disk(); #endif diff --git a/test/test_all.hpp b/test/test_all.hpp index 2911f9f6b06..685c2356ddf 100644 --- a/test/test_all.hpp +++ b/test/test_all.hpp @@ -21,6 +21,6 @@ #include -int test_all(realm::util::Logger* = nullptr, bool disable_all_sync_to_disk = true); +int test_all(realm::util::Logger* = nullptr); #endif // REALM_TEST_TEST_ALL_HPP diff --git a/test/test_transform.cpp b/test/test_transform.cpp index 84ea5eaf00f..c1a3d2bf6e5 100644 --- a/test/test_transform.cpp +++ b/test/test_transform.cpp @@ -972,8 +972,8 @@ TEST(Transform_EraseSelectedLinkView) } } - -TEST(Transform_Randomized) +// this test can take upwards of an hour if sync to disk is enabled +TEST_IF(Transform_Randomized, get_disable_sync_to_disk()) { const char* trace_p = ::getenv("UNITTEST_RANDOMIZED_TRACE"); bool trace = trace_p && (StringData{trace_p} != "no"); diff --git a/test/util/test_path.cpp b/test/util/test_path.cpp index 6a2bfefc459..c64b773c8f9 100644 --- a/test/util/test_path.cpp +++ b/test/util/test_path.cpp @@ -161,7 +161,9 @@ bool test_dir_is_exfat() REALM_ASSERT_RELEASE(ret == 0); // The documentation and headers helpfully don't list any of the values of // f_type or provide constants for them - return fsbuf.f_type == 28 /* exFAT */; + std::string fs_typename = fsbuf.f_fstypename; + std::transform(fs_typename.begin(), fs_typename.end(), fs_typename.begin(), toLowerAscii); + return fs_typename.find(std::string("exfat")) != std::string::npos; #else return false; #endif diff --git a/tools/run-tests-on-exfat.sh b/tools/run-tests-on-exfat.sh index daa47fdfedf..f736419d4db 100755 --- a/tools/run-tests-on-exfat.sh +++ b/tools/run-tests-on-exfat.sh @@ -1,15 +1,24 @@ #!/usr/bin/env bash -set -e +set -e -x readonly build_dir="$PWD" readonly dmg_file="$build_dir/exfat.dmg" -if ! [ -f "$build_dir/test/realm-tests" ]; then +build_prefix="not found" +if [ -f "$build_dir/test/realm-tests.app/Contents/MacOS/realm-tests" ]; then + build_prefix="$build_dir/test/" +elif [ -f "$build_dir/test/Release/realm-tests.app/Contents/MacOS/realm-tests" ]; then + build_prefix="$build_dir/test/Release/" +elif [ -f "$build_dir/test/Debug/realm-tests.app/Contents/MacOS/realm-tests" ]; then + build_prefix="$build_dir/test/Debug/" +else echo 'Run this script from the build directory after building tests' exit 1 fi +echo "using path prefix $build_prefix" + function cleanup() { rm -f "$dmg_file" if [ -n "$device" ]; then @@ -19,10 +28,12 @@ function cleanup() { trap cleanup EXIT rm -f "$dmg_file" -hdiutil create -fs exFAT -size 100MB "$dmg_file" +hdiutil create -fs exFAT -size 400MB "$dmg_file" hdiutil_out=$(hdiutil attach exfat.dmg) device=$(echo "$hdiutil_out" | head -n1 | cut -f1 | awk '{$1=$1};1') path=$(echo "$hdiutil_out" | tail -n1 | cut -f3) -./test/realm-tests "$path/" +UNITTEST_ENABLE_SYNC_TO_DISK=1 "$build_prefix/realm-tests.app/Contents/MacOS/realm-tests" "$path/" +UNITTEST_ENABLE_SYNC_TO_DISK=1 "$build_prefix/realm-sync-tests.app/Contents/MacOS/realm-sync-tests" "$path/" +echo "finished running tests"