nuclearace / Socket.IO-Client-Swift

socket.io-client for Swift
Other
361 stars 53 forks source link

Crashes on reconnection #32

Closed osgafarov closed 9 years ago

osgafarov commented 9 years ago

Hi,

I am using Socket.IO-Client-Swift in a project written in Objective-C. I still support iOS 7.1

I encounter one crash on line 291 in SocketEngine.swift

    if self.connected {

        assert(false, "We're in a bad state, this shouldn't happen.") //crashes here
    }

Steps to reproduce:

  1. Go to first screen of the app. Open a socket connection.
  2. Lock the screen of the device for 20-30 seconds.
  3. Unlock the screen and quickly navigate away from the current view controller of the app to another view controller. This will call socket.close()
  4. In a few seconds the socket library tries to reconnect and then it goes to this "bad" state.

Do you have any ideas guys how to fix it?

Thanks in advance.

nuclearace commented 9 years ago

First, I'd suggest updating the client.

Second, this is probably happening because iOS is terrible for background connections. I'm not an iOS dev, so I don't really know the best practice for it, but I think you should be closing the socket and then re-add a new one or try to reopen the same one. It's happening because it's not being cleanly closed on a lock.

nuclearace commented 9 years ago

With the new client there's a new close method. With Objective-C I think (I don't know Objective-C well) you'd call it like:

[socket closeWithFast:YES];

Which basically has the client assume that the server gets the disconnect, and immediately calls the disconnect handler.

nuclearace commented 9 years ago

Actually there's a case where it can explode.

osgafarov commented 9 years ago

I have tried with

[socket closeWithFast:YES];

But it did not help. Instead it crashed in another place. So I will wait for a fix and if it does not help, then I will go with closing the connection manually, when the screen is being locked.

Thanks!

nuclearace commented 9 years ago

Where did it crash when you closed fast?

osgafarov commented 9 years ago

It is random and sometimes it is difficult to get meaningful stack trace. But at least I can confirm, that sometimes it crashes on line 603 in SocketEngine.swift:

self.client.webSocketDidCloseWithCode(1, reason: "Socket Disconnect", wasClean: true) (EXC_BAD_ACCESS)

waphumanoid commented 9 years ago

Hi. I am in testing mode with my ios app with the socket io lib. I found a case when it comes to crash (using iphone 5s / ios 8.2). On first start it runs well but when I begin to switch the iphone airplane mode on/off (to disable all the network connectons) repeatedly during 1-5 seconds and click home button to send the app to the suspend mode and call it back, it crashes after a few such attempts.

The environment:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [SomeClass closeIOSocket];
}

// In SomeClass:
- (void)closeIOSocket
{
    [chatIOSocket closeWithFast:NO];
    chatIOSocket = nil;
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [SomeClass connectIOSocket];
}

// In SomeClass:
- (void)connectIOSocket
{
    chatIOSocket = [[SocketIOClient alloc] initWithSocketURL:kWSServerUrl options:@{@"forceWebsockets":@YES}];
    …
}

Some snippets from a log:

Should do event: reconnectAttempt with data: Optional([-3])
Warning! This socket was previously closed. This might be dangerous!
Should do event: disconnect with data: Optional([WebSocket closed])
Should do event: reconnect with data: Optional([… . (kCFErrorDomainCFNetwork, error 2)])
Should do event: reconnectAttempt with data: Optional([-1])
...
Should do event: connect with data: nil
Should do event: reconnectAttempt with data: Optional([-6])
Warning! This socket was previously closed. This might be dangerous!
Should do event: reconnectAttempt with data: Optional([-5])
Warning! This socket was previously closed. This might be dangerous!
Should do event: disconnect with data: Optional([WebSocket closed])

And some screenshots of the crash debug stack. As far as I understand there's some issue with lib's slave background threads to clean.

screen shot 2015-04-04 at 19 07 23 screen shot 2015-04-04 at 19 07 51 screen shot 2015-04-04 at 19 08 29

waphumanoid commented 9 years ago

A small update to the upper comment: to reproduce the crash easier just switch off any network connections and repeatedly send the app to the background and back with no delay. After several attempts it begins to show

...
Should do event: reconnectAttempt with data: Optional(...)
Warning! This socket was previously closed. This might be dangerous!
...

and catches a crash. During these attempts the memory increases dramatically, I guess it leaks.

nuclearace commented 9 years ago

Hm, when I wrote the the app this was based on, I actually used reachability to test for network loss. And if it went from wifi -> cell I'd readd the socket. I'd have to see what else there is I can do.

I don't actually test on iOS, but I'll look into it

nuclearace commented 9 years ago

@waphumanoid okay, well I think I found a reason your code is exploding.

nuclearace commented 9 years ago

https://github.com/socketio/socket.io-client-swift/releases/tag/v1.5.1 should fix your crash @waphumanoid