Skip to content

Commit

Permalink
Add a fallback to full sync if fcntl(F_BARRIERFSYNC) fails (#5806)
Browse files Browse the repository at this point in the history
* Add a fallback to full sync if fcntl(F_BARRIERFSYNC) fails

F_BARRIERFSYNC is available on HFS and APFS, but is not supported
on filesystems such as exFAT.

* conditionally run a sync test

* more robust paths for various build types
  • Loading branch information
ironage authored Sep 2, 2022
1 parent 8ee550c commit d6ef0c2
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))


Expand Down
12 changes: 12 additions & 0 deletions evergreen/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
6 changes: 3 additions & 3 deletions src/realm/util/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions test/test_all.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion test/test_all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@

#include <realm/util/logger.hpp>

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
4 changes: 2 additions & 2 deletions test/test_transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
4 changes: 3 additions & 1 deletion test/util/test_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 15 additions & 4 deletions tools/run-tests-on-exfat.sh
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"

0 comments on commit d6ef0c2

Please sign in to comment.