Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception unification improvements #5911

Merged
merged 12 commits into from
Oct 26, 2022

Conversation

tgoyne
Copy link
Member

@tgoyne tgoyne commented Sep 29, 2022

Most of these changes are related to improving the messages in exceptions thrown by core so that we can pass them on directly to the user rather than having to replace them with better errors in the SDK. With these changes, there's only a small number of places where Cocoa modifies the messages thrown by core, and they're all clearly linked to Cocoa-specific quirks.

This also greatly expands the testing of the exceptions thrown by core, as there were a number of places where Cocoa tests identified errors with messages that were simply wrong. Every instance of REQUIRE_THROWS() in the object store tests has been replaced with a more precise assertion which validations that the expected thing is being thrown; in most cases with REQUIRE_EXCEPTION(), which is a new test macro which checks that the exception is a realm::Exception, has the expected error code, and validates the exception message (either using a literal string or a Catch matcher). This revealed a few places where tests weren't testing the thing they intended to test, many places where things other than realm::Exception were being thrown, and a lot of spots where error messages could just be better.

The binary size increased by quite a bit with the exception unification branch, so I made some localized changes to address this. Giving each of the exception types a non-inline virtual function makes it so that the vtables for the exception types aren't inline and thus aren't emitted into every since TU which includes the header (which is most of them). This cuts about a megabyte of a static library build. The std::map for converting error code names to codes also had surprisingly bad codegen due to building the map at runtime, and replacing it with a statically sorted array both reduces the size and improves startup perf.

@tgoyne tgoyne self-assigned this Sep 29, 2022
@cla-bot cla-bot bot added the cla: yes label Sep 29, 2022
@bmunkholm
Copy link
Contributor

@tgoyne How much bigger is the binary now with this PR?

@tgoyne
Copy link
Member Author

tgoyne commented Sep 30, 2022

Current sizes of Realm.framework:

branch static dynamic
master 114,406 KB 10,325 KB
feature/exception-unification 115,499 KB 10,374 KB
tg/exception-unification 114,877 KB 10,356 KB

@tgoyne tgoyne force-pushed the tg/exception-unification branch 2 times, most recently from 7f33825 to a2287ce Compare October 5, 2022 01:24
@jedelbo jedelbo mentioned this pull request Oct 7, 2022
@tgoyne tgoyne changed the base branch from feature/exception-unification to je/exception-unification October 8, 2022 00:06
@tgoyne tgoyne force-pushed the tg/exception-unification branch 10 times, most recently from 4c3fddb to fb7a3a1 Compare October 10, 2022 01:50
Base automatically changed from je/exception-unification to feature/exception-unification October 10, 2022 09:18
This was referenced Oct 10, 2022
@tgoyne tgoyne force-pushed the tg/exception-unification branch 6 times, most recently from ac0df23 to ccc8a1d Compare October 20, 2022 23:15
Comment on lines -709 to -714
// Create a deep copy of the file_path string, otherwise it can appear that
// users are leaking paths because string assignment operator implementations might
// actually be reference counting with copy-on-write. If our all_files map
// holds onto these references (since it is still reachable memory) it can appear
// as a leak in the user application, but it is actually us (and that's ok).
const std::string path = file_path.c_str();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a workaround for a c++03 thing (copy-on-write std::string) which hasn't been applicable since c++11.

@@ -85,31 +85,35 @@ UnsupportedFileFormatVersion::UnsupportedFileFormatVersion(int version)
UnsupportedFileFormatVersion::~UnsupportedFileFormatVersion() noexcept = default;


LogicError::LogicError(ErrorCodes::Error code, const std::string& msg)
LogicError::LogicError(ErrorCodes::Error code, std::string_view msg)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one or two spots where being able to pass in a string_view is nice, and that ends up being a viral change that needs to propagate all the way downwards so it touches all of these.

@@ -122,11 +122,11 @@ ExternalCommitHelper::ExternalCommitHelper(RealmCoordinator& parent, const Realm
std::string temp_dir = util::normalize_dir(config.fifo_files_fallback_path);
std::string sys_temp_dir = util::normalize_dir(DBOptions::get_sys_tmp_dir());
path = DB::get_core_file(config.path, DB::CoreFileType::Note);
bool fifo_created = realm::util::try_create_fifo(path);
bool fifo_created = realm::util::try_create_fifo(path, !temp_dir.empty() || !sys_temp_dir.empty());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change here is making it only swallow the exception if we have more paths to try, which results in a more useful error when we can't create the fifo and don't have a fallback.

@@ -425,31 +425,6 @@ void RealmCoordinator::open_db()
util::File::remove(m_config.path);
return open_db();
}
catch (const FileAccessError& ex) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now is all handled in File::open()

@@ -154,7 +154,7 @@ void SyncSession::become_inactive(util::CheckedUniqueLock lock, Status status)
}

if (!status.get_std_error_code())
status = Status(make_error_code(util::error::operation_aborted), "SyncSession::become_inactive");
status = Status(make_error_code(util::error::operation_aborted), "Sync session became inactive");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error is still not great but correctly reporting why the listener was cancelled turned out to be oddly complicated.

default:
throw FileAccessError(ErrorCodes::FileOperationFailed, msg, path, err); // LCOV_EXCL_LINE
}
}


void remove_dir_recursive(const std::string& path)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't actually used.


template <typename T>
inline T get(Mixed)
{
abort();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main goal of these changes is to eliminate these aborts and replace them with compile-time failures. As a bonus it ends up less verbose and actually compilers faster due to eliminating unreachable template instantiations.

@tgoyne tgoyne force-pushed the tg/exception-unification branch 2 times, most recently from 0b2171b to 6789384 Compare October 21, 2022 01:18
@tgoyne tgoyne marked this pull request as ready for review October 21, 2022 02:35
Copy link
Contributor

@jedelbo jedelbo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tgoyne tgoyne merged commit 506f118 into feature/exception-unification Oct 26, 2022
@tgoyne tgoyne deleted the tg/exception-unification branch October 26, 2022 19:40
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants