flowsprenger / RxLifx-Swift

RxSwift based SDK for the LIFX Lan protocol
MIT License
10 stars 5 forks source link

UdpTransport Crash #11

Closed lightbow closed 6 years ago

lightbow commented 6 years ago

I'm seeing a crash in RxLifx/UdpTransport.swift. (reported as line 167 even though there aren't that many lines in that file, so ignore that part) I can't reproduce it locally, but it's the most-frequent user crash for Lightbow as reported by Crash Reporter according to Xcode. (though still rare in the grand scheme of things). I don't understand what's going wrong yet, but some background thread croaks on (I believe) a socket close():

#0  (null) in close ()
#1  (null) in _T06RxLifx12UdpTransportC8messages0A5Swift10ObservableCy2TMQzGfgAJycfU_AE10Disposable_pAE11AnyObserverVyAIGcfU_yycfU0_Tf4gggg_n at RxLifx/UdpTransport.swift:167
#2  (null) in _T06RxLifx12UdpTransportC8messages0A5Swift10ObservableCy2TMQzGfgAJycfU_AE10Disposable_pAE11AnyObserverVyAIGcfU_yycfU0_TA ()
#3  (null) in _T0Ix_IyB_TR ()
#4  (null) in _dispatch_call_block_and_release ()
#5  (null) in _dispatch_client_callout ()
#6  (null) in _dispatch_root_queue_drain ()
#7  (null) in _dispatch_worker_thread3 ()
#8  (null) in _pthread_wqthread ()
#9  (null) in start_wqthread ()

The swift 4.0.3 demangler spits out the slightly-less-mysterious data for stack frame #1:

function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed, Arg[2] = Owned To Guaranteed, Arg[3] = Owned To Guaranteed> 
of closure #2 () -> () 
in closure #1 (RxSwift.AnyObserver<A.TM>) -> RxSwift.Disposable 
in closure #1 () -> RxSwift.Observable<A.TM> 
in RxLifx.UdpTransport.messages.getter : RxSwift.Observable<A.TM>

and stack frame #2:

partial apply forwarder for closure #2 () -> () 
in closure #1 (RxSwift.AnyObserver<A.TM>) -> RxSwift.Disposable 
in closure #1 () -> RxSwift.Observable<A.TM> 
in RxLifx.UdpTransport.messages.getter : RxSwift.Observable<A.TM>

and stack frame #3:

reabstraction thunk helper from @callee_owned () -> () to @callee_unowned @convention(block) () -> ()
flowsprenger commented 6 years ago

I am also failing to reproduce so far :/ I can't even get the socket to close, as it is bound to no specific interface it just continues to work and receive its own broadcasts with Wifi and mobile data both disabled, turning it on and off. There are two sockets one for any port that is used for outgoing messages and incoming from anything but very old Originals, and 56700 receiving responses from old Originals (that always respond to 56700). My hunch was that maybe something in RxSwift.Disposable does not deal well with both source sockets closing at the same time (the two sockets produce messages into the same observable), but who knows. I might have a try if I can reproduce when programatically forcing the socket after a while

lightbow commented 6 years ago

I think it may have something to do with sockets closing in the background if the phone is put to sleep for a minute or so, and then relaunching the app into an immediate crash. I'll see if I can get it to repro with the RxLifxExample app.

flowsprenger commented 6 years ago

Good thinking @lightbow I managed to reproduce it coming back from sleep. Apparently the networking code can signal a SIGPIPE signal under those conditions: https://stackoverflow.com/questions/32197319/network-code-stopping-with-sigpipe That should be easy to fix.