-
Notifications
You must be signed in to change notification settings - Fork 136
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
RUMM-448 Improve NWPathMonitor
thread safety
#109
Merged
ncreated
merged 1 commit into
master
from
ncreated/RUMM-448-improve-nwpath-monitor-safety
May 18, 2020
Merged
RUMM-448 Improve NWPathMonitor
thread safety
#109
ncreated
merged 1 commit into
master
from
ncreated/RUMM-448-improve-nwpath-monitor-safety
May 18, 2020
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9bc5322
to
87ee84b
Compare
buranmert
previously requested changes
May 16, 2020
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.
Very useful insight from #110
- iOS 11 is okay: proves
NWPathMonitor
is the root cause - Crash rate 500/~3M: this rate seems consistent to me with thread safety of read/write of
currentPath
hypothesis
One shouldn't review thread-safety at 2 AM
@buranmert Yes, #110 brought some new light to the problem. We should avoid
I updated the PR and description accordingly. |
This was
linked to
issues
May 18, 2020
buranmert
suggested changes
May 18, 2020
buranmert
approved these changes
May 18, 2020
ab6bb81
to
23305e1
Compare
23305e1
to
3da2053
Compare
Merged
2 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What and why?
🔬 This PR attempts to fix issues with
NWPathMonitor
that were reported by several people. Unfortunately, I wasn't able to reproduce any of reports, so all the changes are based on my research, investigation and intuition.GH Issue #110
Provided crash logs clearly says we have a problem with some parts of
NWPath
being destroyed while we're accessing it insideNWPathMonitor.current
:Even when we capture the value of
struct NWPath
on local property, this code seems to not be thread safe:My suspicion is that the
NWPath
internals are based on mutable state, thus it crashes when theNWPath
is updated by the OS.Issue reported by @jegnux:
swift_unknownObjectRelease
crash during background → foreground transition (and probably network connection status change - not sure):GH Issue #70:
This is clearly the same problem:
Other issues
There is a small chance that the
NWPathMonitor
might be the root cause of #106. In this case, we don't have a symbolicated crashlog, so we can't really tell ifdyld_stub_binder
attempts to evaluate a symbol coming fromDarwin
→Network
image, but this is IMO possible, asNWPathMonitor's
start()
is invoked at the SDK initialization time.How?
Debugging
To reproduce the issue, I was trying different combinations of following:
DispatchQueue.concurrentPerform(iterations: 10_000)
to stress testnwPathMonitor.currentPath
access from multiple threads.After many runs, I still didn't catch the crash.
The fix
First, I got rid of
fetch {}
andcancel {}
closures, which were the only things retainingNWPathMonitor
instance. Instead, the monitor is now retained on the property explicitly. Even if it doesn't help, it simplifies the code and should result with cleaner / different stack trace if the issue is back.Second, looking at the same problem solved in
rwbutler/Connectivity
project, I decided to update our way of handling theNWPathMonitor
. This monitor provides to ways of accessing theNWPath
:monitor.currentPath
;monitor.pathUpdateHandler = { path in _ }
.The pulling model is very convenient for other parts of the SDK, but its documentation doesn't give any guidelines on how to deal with a thread safety (same, when we look at this implementation, we can only guess what happens internally).
The pushing model is more explicit - it promises to deliver updates on the
queue
passed tomonitor.start(queue:)
. To leverage both, the thread safety of the pushing model, and keep the convenience of the pulling model, I created a wrapper which exposes.current
value while using.pathUpdateHandler = { _ in }
internally.Because
rwbutler/Connectivity
successfully usesmonitor.pathUpdateHandler = { _ in }
to read network info, I hope this will ultimately solve also our problem.In addition to this PR, I opened a thread on Apple Developer Forum, to hopefully get some more insights on
NWPath
thread safety:https://forums.developer.apple.com/message/420389#420389
Review checklist
tracing
branch, as we have better setup for running unit tests on device. When approved, I will rebase it ontomaster
.