-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Remove try! statement from FailableIterator #785
Conversation
My team has recently experienced crashes of an app in production related to SQLite.swift. Upon further review, we discovered that these crashes are occurring due to this `try!` encountering a `throw` from `failableNext()`. This PR resolves the issue by returning nil if a throw is encountered. Here is the entire thread that crashes. Note that it occurs when using the Apollo-iOS framework, found (https://github.com/apollographql/apollo-ios)[here]: ``` Thread 7 name: Thread 7 Crashed: 0 libswiftCore.dylib 0x000000010117f968 0x100fa0000 + 1964392 1 libswiftCore.dylib 0x000000010117f968 0x100fa0000 + 1964392 2 libswiftCore.dylib 0x000000010102f994 0x100fa0000 + 588180 3 SQLite 0x0000000100d7e80c _T06SQLite16FailableIteratorPAAE4next7ElementQzSgyFAA9StatementC_Tg5 + 212 (Statement.swift:211) 4 SQLite 0x0000000100d674c8 _T06SQLite10ConnectionC7prepares11AnySequenceVyAA3RowVGAA9QueryType_pKFs0D8IteratorVyAHGycfU_AHSgycfU_TA + 76 (Query.swift:927) 5 SQLite 0x0000000100d67578 _T06SQLite3RowVSgIxo_ADIxr_TRTA + 48 (Query.swift:0) 6 libswiftCore.dylib 0x000000010114e9bc 0x100fa0000 + 1763772 7 libswiftCore.dylib 0x000000010114e9fc 0x100fa0000 + 1763836 8 libswiftCore.dylib 0x000000010114ead0 0x100fa0000 + 1764048 9 libswiftCore.dylib 0x000000010102a8c8 0x100fa0000 + 567496 10 libswiftCore.dylib 0x000000010114e16c 0x100fa0000 + 1761644 11 libswiftCore.dylib 0x000000010118fd78 0x100fa0000 + 2030968 12 libswiftCore.dylib 0x0000000100fa8774 0x100fa0000 + 34676 13 libswiftCore.dylib 0x000000010115f5bc 0x100fa0000 + 1832380 14 libswiftCore.dylib 0x000000010114f4fc 0x100fa0000 + 1766652 15 Apollo 0x0000000100a01c3c _T06Apollo21SQLiteNormalizedCacheC13selectRecords33_0382DE2BE0B0836588D3F2CA65C602E7LLSayAA6RecordVGSaySSG7forKeys_tKFTf4gn_n + 1284 (SQLiteNormalizedCache.swift:0) 16 Apollo 0x0000000100a02710 _T06Apollo21SQLiteNormalizedCacheC12mergeRecords33_0382DE2BE0B0836588D3F2CA65C602E7LLs3SetVySSGAA06RecordO0V7records_tKFTf4gn_n + 116 (SQLiteNormalizedCache.swift:0) 17 Apollo 0x0000000100a031c8 _T06Apollo21SQLiteNormalizedCacheC5mergeAA7PromiseCys3SetVySSGGAA06RecordG0V7records_tFTf4gn_n + 304 (SQLiteNormalizedCache.swift:0) 18 Apollo 0x00000001009ff290 _T06Apollo21SQLiteNormalizedCacheCAA0cD0A2aDP5mergeAA7PromiseCys3SetVySSGGAA06RecordG0V7records_tFTW + 44 (SQLiteNormalizedCache.swift:0) 19 Apollo 0x000000010099d1ec _T06Apollo0A5StoreC7publishAA7PromiseCyytGAA9RecordSetV7records_SvSg7contexttFyyyc_ys5Error_pctcfU_yycfU_Tf4ggng_n + 164 (ApolloStore.swift:52) 20 Apollo 0x000000010099f788 _T06Apollo0A5StoreC7publishAA7PromiseCyytGAA9RecordSetV7records_SvSg7contexttFyyyc_ys5Error_pctcfU_yycfU_TA + 104 (ApolloStore.swift:0) 21 Apollo 0x00000001009c0f1c _T0Ix_IyB_TR + 36 (GraphQLQueryWatcher.swift:0) 22 libdispatch.dylib 0x00000001812b2a54 _dispatch_call_block_and_release + 24 (init.c:994) 23 libdispatch.dylib 0x00000001812b2a14 _dispatch_client_callout + 16 (object.m:502) 24 libdispatch.dylib 0x00000001812c1540 _dispatch_queue_concurrent_drain + 540 (inline_internal.h:2500) 25 libdispatch.dylib 0x00000001812bd304 _dispatch_queue_invoke$VARIANT$mp + 348 (queue.c:5304) 26 libdispatch.dylib 0x00000001812bfcf4 _dispatch_root_queue_drain + 600 (inline_internal.h:2539) 27 libdispatch.dylib 0x00000001812bfa38 _dispatch_worker_thread3 + 120 (queue.c:6104) 28 libsystem_pthread.dylib 0x000000018155b06c _pthread_wqthread + 1268 (pthread.c:2286) 29 libsystem_pthread.dylib 0x000000018155ab6c start_wqthread + 4 ```
@stephencelis any chance this could get a review/merge soon? |
Hi @ethansinjin! Thanks for the submission! I've handed off maintenance, but hopefully @jberkel could give it a quick look to make sure it doesn't break anything? |
@ethansinjin it's called If I remember correctly the problem is that Swift's iterator protocol doesn't assume that the iteration can produce errors. What's the error thrown in your case? |
@jberkel: EXC_BAD_INSTRUCTION fatal error: unexpectedly found nil while unwrapping an Optional value I see what you mean; perhaps returning nil isn't the "correct" thing to do, but using |
@ethansinjin unwrapping an optional value? that sounds like it's not the immediate cause. would expect to see some error thrown from within SQLite. |
My apologies, I don't think that's the actual crash. Query.swift line 927:
Thich calls
Because The Swift Programming Language Docs section on Error Handling, specifically "Disabling Error Propagation":
Please let me know if there's any more information I can provide! Also of note is the Statement.swift lines 185 to 187, which are the next step up the call stack:
I think this may have something to do with the initial crash. I think the |
Have a look at the check function (Connection:642) func check(_ resultCode: Int32, statement: Statement? = nil) throws -> Int32 {
guard let error = Result(errorCode: resultCode, connection: self, statement: statement) else {
return resultCode
}
throw error
} It's very likely that the error gets thrown from there, which means that SQLite returned an error code. You should see this error somewhere in the log output. If not, try to put a breakpoint at the line where the error is thrown and run it in the debugger. |
We've run into this crash as well when From my understanding, and as @ethansinjin discusses above, the After looking at the options for a fix, it seems like this is perhaps a deeper design issue. I see two options two prevent the crash:
Let me know which option seems like the best next step, or if there's another alternative I'm not considering. on an entirely separate note 👋 @ethansinjin hope things are well! |
We have run into the same crash. Any chance that you can take a look? thanks! CC: @jberkel |
Hey @jberkel, i am getting "Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: disk I/O error (code: 10)" with
Do you think Is this pr resolves this issue or i should consider other solutions? |
Hello, I am having the same issue, and I've read this thread and I think I understand? 2 thoughts.
Though the function signature is curious as it returns nullable. So in conclusion, what is "failable" in your definition here? I realize the proposal doesn't conform to IteratorProtocol, so I just need more context. It should be noted that another library which uses this library, wraps it in a Promise API. And the way promises work, is that they catch exceptions from within the promise context. So in essence you use a promise to have safe error recoverable interface that is simply analogous to |
How about this change?
to this:
|
Actually, about this the previous change I just mentioned, and the change for this PR? The reason behind this is because now that I see the use case of |
@@ -208,7 +208,10 @@ public protocol FailableIterator : IteratorProtocol { | |||
|
|||
extension FailableIterator { | |||
public func next() -> Element? { | |||
return try! failableNext() | |||
if let next = try? failableNext() { |
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.
You could simply write return try? failableNext()
instead of return try! failableNext()
. There's no need to use if let
here.
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.
No this raises Value of optional type 'Self.Element??' not unwrapped; did you mean to use 'try!' or chain with '?'?
Same as stephencelis#785 but implemented with a lighter syntax.
Hi, We are experiencing the same issues. Will this patch be merged into master? We need to find a solution that will last, seen many people implement this change locally but we are keen on not branching out this library for future compatibility Thanks! |
I'd also like to know if this is going to be merged? Cause I am seeing the same issue in my crashreports. Can't reproduce it locally though.. |
FWIW my company ended up forking this repo as it doesn't seem to be actively maintained anymore. We did this mainly to just pull the change in this PR. |
Closing as this was fixed by another PR (replacing the ! by a ?) |
@nathanfallet which PR? |
@kylebrowning it was #1030, which was later reverted in #1075. |
So its not fixed? |
See #1030 if you need more details |
My team has recently experienced crashes of an app in production related to SQLite.swift. Upon further review, we discovered that these crashes are occurring due to this
try!
encountering athrow
fromfailableNext()
.This PR resolves the issue by returning nil if a throw is encountered.
Here is the entire thread that crashes. Note that it occurs when using the Apollo-iOS framework, found here: