Skip to content

Crashes observed in OutputFileStream due to EXC_BAD_ACCESS. #177

@dcow

Description

@dcow

Recently we've noticed crashes coming from the new OutputFileStream code. An example stack trace is included at the end of this issue.

While digging into this, we noticed the switch from the foundation FileHandle API to the older POSIX API. The rationale presumably is the deprecation of the write(data: Data) function. This left us perplexed and we believe this to be a misunderstanding. The specific write(data: Data) function was deprecated, yes, but it was replaced with the generic write<T>(contentsOf: T) throws where T : DataProtocol function. As well as being more flexible in its input parameter, the new function also properly communicates errors via throws (related: unhandled exceptions at the write(data: Data) call site was previously an issue we saw coming from your code). It is a welcome replacement (:

If I may, it seems the best course of action would be to remove the OutputFileStream addition, specifically, and simply update the code as it was previously so that it uses the non-deprecated write function from FileHandle. And, the new API forces you to handle the errors I mentioned we had also been encountering, 2 birds...

But, if you must stick with the POSIX API, which, while fun to use at times, I would strongly discourage, then the implementation needs some work. There are numerous issues (lack of handling for short writes, unnecessary string conversions, generally thread safety, dubious pointer handling, etc.) which I'm happy to help you through if you decide to stick with this route. But, it's super tricky to get all this right when using the POSIX API hence why the first class Apple-supported Foundation APIs are preferred over the POSIX ones.

Hardware Model:     iPhone14,3
Process:            Uno
Identifier:         app.Uno
Version:            1.0
Role:               Background
OS Version:         iOS 16.0
Exception Type:     EXC_BAD_ACCESS 
Exception Subtype:  KERN_INVALID_ADDRESS


EXC_BAD_ACCESS: Attempted to dereference garbage pointer 0x68.

0  libsystem_c.dylib _flockfile
1  libsystem_c.dylib _fwrite
2  Uno               closure #1 in OutputFileStream.write(_:) (OutputFileStream.swift:69:17)
3  Uno               specialized String.UTF8View.withContiguousStorageIfAvailable<A>(_:) (<compiler-generated>)
4  Uno               OutputFileStream.write(_:) (OutputFileStream.swift:67:29)
5  Uno               closure #1 in Storage.write<A>(_:value:) (Storage.swift:42:26)
6  Uno               thunk for @callee_guaranteed () -> () (<compiler-generated>)
7  Uno               thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
8  libdispatch.dylib __dispatch_client_callout
9  libdispatch.dylib __dispatch_lane_barrier_sync_invoke_and_complete
10 Uno               Storage.write<A>(_:value:) (Storage.swift:37:19)
11 Uno               SegmentDestination.queueEvent<A>(event:) (SegmentDestination.swift:126:17)
12 Uno               SegmentDestination.execute<A>(event:) (SegmentDestination.swift:106:13)
13 Uno               specialized closure #1 in Mediator.execute<A>(event:) (Timeline.swift:78:32)
14 Uno               specialized Timeline.process<A>(incomingEvent:) (Timeline.swift:37:13)
15 Uno               closure #1 in StartupQueue.replayEvents() (StartupQueue.swift:60:28)
16 Uno               thunk for @callee_guaranteed () -> () (<compiler-generated>)
17 Uno               thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
18 libdispatch.dylib __dispatch_client_callout
19 libdispatch.dylib __dispatch_lane_barrier_sync_invoke_and_complete
20 Uno               StartupQueue.replayEvents() (StartupQueue.swift:58:19)
21 Uno               closure #1 in StartupQueue.analytics.didset (StartupQueue.swift:21:23)
22 Uno               thunk for @escaping @callee_guaranteed (@in_guaranteed A) -> () (<compiler-generated>)
23 Uno               thunk for @escaping @callee_guaranteed (@in_guaranteed A) -> (@out ()) (<compiler-generated>)
24 Uno               closure #1 in Store.notify<A>(subscribers:state:) (Store.swift:250:21)
25 Uno               thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
26 libdispatch.dylib __dispatch_call_block_and_release
27 libdispatch.dylib __dispatch_client_callout
28 libdispatch.dylib __dispatch_main_queue_drain
29 libdispatch.dylib __dispatch_main_queue_callback_4CF
30 CoreFoundation    ___CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
31 CoreFoundation    ___CFRunLoopRun
32 CoreFoundation    _CFRunLoopRunSpecific
33 GraphicsServices  _GSEventRunModal
34 UIKitCore         -[UIApplication _run]
35 UIKitCore         _UIApplicationMain
36 SwiftUI           0x18a82fce4 (0x18a82fc40 + 164)
37 SwiftUI           0x18a78cc20 (0x18a78cb8c + 148)
38 SwiftUI           0x18a775b40 (0x18a775ac4 + 124)
39 Uno               static App.$main() (App.swift:74:1)
40 dyld              start

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions