-
Notifications
You must be signed in to change notification settings - Fork 586
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
Fix error that caused a segfault when users registered custom Sync logger functions #4156
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job. Was it basically that the function provided by the user was not owned by SyncLoggerDelegator and was therefore free to be garbage collected, eventually leading to a use after free of the callback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome ❤️
tests/js/session-tests.js
Outdated
const realm = await Realm.open(config); | ||
realm.close(); | ||
|
||
TestCase.assertTrue(loggerInvoked, "Custom logger should have been invoked"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit worry for a race condition here but maybe Realm.open()
takes long enough.
My understanding is that the In the old implementation, there was a |
tests/js/session-tests.js
Outdated
let loggerInvoked = false; | ||
Realm.App.Sync.setLogLevel(app, "info"); // "all", "trace", "debug", "detail", "info", "warn", "error", "fatal", "off" | ||
Realm.App.Sync.setLogger(app, (level, message) => (loggerInvoked = true)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it might not hurt to test that level
and message
are passed through correctly?
let loggerInvoked = false; | |
Realm.App.Sync.setLogLevel(app, "info"); // "all", "trace", "debug", "detail", "info", "warn", "error", "fatal", "off" | |
Realm.App.Sync.setLogger(app, (level, message) => (loggerInvoked = true)); | |
let loggedLevel, loggedMessage; | |
Realm.App.Sync.setLogLevel(app, "info"); // "all", "trace", "debug", "detail", "info", "warn", "error", "fatal", "off" | |
Realm.App.Sync.setLogger(app, (level, message) => { | |
if (!loggedLevel) loggedLevel = level; | |
if (!loggedMessage) loggedMessage = message; | |
}); | |
// ... | |
TestCase.assertEqual(loggedLevel, 123); | |
TestCase.assertEqual(loggedMessage, "whatever the first message is"); |
Or is the first message not predictable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is as long as the sync subsystem doesn't change what it returns, or the sync config structure doesn't change. It'd be weird if the test failed because of that, but I'll see if I can parse out from the lower levels how the message is constructed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't worry too much if it's awkward :)
Yes, basically we were passing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a minor comment here - feel free to integrate the suggestion or merge at will.
tests/js/session-tests.js
Outdated
}); | ||
|
||
const realm = await Realm.open(config); | ||
const loggerInvoked = await promisedLog; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no real meaning in returning and asserting true. If it doesn't happen the promise won't resolve and the test will simply time out.
const loggerInvoked = await promisedLog; | |
await promisedLog; |
tests/js/session-tests.js
Outdated
const realm = await Realm.open(config); | ||
const loggerInvoked = await promisedLog; | ||
realm.close(); | ||
TestCase.assertTrue(loggerInvoked, `Custom logger should have registered an '${logLevelStr}' message`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestCase.assertTrue(loggerInvoked, `Custom logger should have registered an '${logLevelStr}' message`); |
Realm.App.Sync.setLogger(app, (level, message) => { | ||
if (level == logLevelNum && message.includes("Connection") && message.includes("Session")) { | ||
// we should, at some point, receive a log message that looks like | ||
// Connection[1]: Session[1]: client_reset_config = false, Realm exists = true, client reset = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want the test to rely on this message to eventually be logged, you could resolve conditionally on the message?
What, How & Why?
This closes #4121
☑️ ToDos
Compatibility
label is updated or copied from previous entryBreaking
label has been applied or is not necessaryIf this PR adds or changes public API's: