Skip to content
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

Crash in RTCPeerConnection.close() #161

Closed
ibc opened this issue Apr 14, 2016 · 20 comments
Closed

Crash in RTCPeerConnection.close() #161

ibc opened this issue Apr 14, 2016 · 20 comments
Assignees

Comments

@ibc
Copy link
Collaborator

ibc commented Apr 14, 2016

After merging #159 (so cordova-ios 4 is used) and #160, calling peerConnection.close() crashes with:

captura de pantalla 2016-04-14 a las 12 34 44

It does not crash as follows:

func RTCPeerConnection_close(command: CDVInvokedUrlCommand) {
        NSLog("iosrtcPlugin#RTCPeerConnection_close()")

        let pcId = command.argumentAtIndex(0) as! Int
        let pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]

        if pluginRTCPeerConnection == nil {
            NSLog("iosrtcPlugin#RTCPeerConnection_close() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
            return;
        }

        dispatch_async(self.queue) {
            pluginRTCPeerConnection!.close()
        }

        // Remove the pluginRTCPeerConnection from the dictionary.
        self.pluginRTCPeerConnections[pcId] = nil
    }

I've also tried passing [weak pluginRTCPeerConnection] in to dispatch_async() but it crashes as well, so I'm worried whether the native object is not properly deallocated.

If so, would this work?

        dispatch_async(self.queue) {
            pluginRTCPeerConnection!.close()
            pluginRTCPeerConnection = nil
        }

/cc @oNaiPs

@ibc
Copy link
Collaborator Author

ibc commented Apr 14, 2016

Well, I mean this:

func RTCPeerConnection_close(command: CDVInvokedUrlCommand) {
    NSLog("iosrtcPlugin#RTCPeerConnection_close()")

    let pcId = command.argumentAtIndex(0) as! Int
    var pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]

    if pluginRTCPeerConnection == nil {
        NSLog("iosrtcPlugin#RTCPeerConnection_close() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
        return;
    }

    dispatch_async(self.queue) {
        pluginRTCPeerConnection!.close()
        pluginRTCPeerConnection = nil
    }

    // Remove the pluginRTCPeerConnection from the dictionary.
    self.pluginRTCPeerConnections[pcId] = nil
}

@ibc
Copy link
Collaborator Author

ibc commented Apr 14, 2016

I've committed the above code to avoid the crash, but I understand this must be re-checked.

@ibc ibc self-assigned this Apr 14, 2016
@mark-veenstra
Copy link
Contributor

@saghul even with the fix you got a crash? I am going to test this now also here

@ibc
Copy link
Collaborator Author

ibc commented Apr 14, 2016

With the already applied commit I don't get the crash.

@oNaiPs
Copy link
Contributor

oNaiPs commented Apr 14, 2016

@ibc i'm sorry I think I forgot to modify that function in my previous PR. Would this work?

Perhaps the problem is because when you do self.pluginRTCPeerConnections[pcId] = nil there are no more references to the RTCPeerConnection, so when dispatch_async is executed, the variable was already dealllocated. Could you try to put this line inside the dispatch_async after calling close()?

@oNaiPs
Copy link
Contributor

oNaiPs commented Apr 14, 2016

Oh, and make sure you do [weak pluginRTCPeerConnection, unowned self]

@saghul
Copy link
Collaborator

saghul commented Apr 14, 2016

I tested master a few hours ago, will test it again shortly.
On Apr 14, 2016 14:59, "José Pereira" [email protected] wrote:

Oh, and make sure you do [weak pluginRTCPeerConnection, unowned self]


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#161 (comment)

@saghul
Copy link
Collaborator

saghul commented Apr 14, 2016

Tested again, with latest master and everything works as expected, great work everyone! 😍

@mark-veenstra
Copy link
Contributor

Same here, no issues! Thanks for the work!

@ibc
Copy link
Collaborator Author

ibc commented Apr 15, 2016

@saghul @mark-veenstra, current master was "fixed" by me yesterday so it does not crash, but as @oNaiPs said above some changes most be done for the PeerConnection to be released.

@ibc
Copy link
Collaborator Author

ibc commented Apr 15, 2016

@oNaiPs wouldn't also need [..., unowned self] here?:

dispatch_async(self.queue) { [weak pluginRTCPeerConnection] in
            pluginRTCPeerConnection?.createOffer(options,
                callback: { (data: NSDictionary) -> Void in
                    self.emit(command.callbackId,
                        result: CDVPluginResult(status: CDVCommandStatus_OK, messageAsDictionary: data as [NSObject : AnyObject])
                    )
                },
                errback: { (error: NSError) -> Void in
                    self.emit(command.callbackId,
                        result: CDVPluginResult(status: CDVCommandStatus_ERROR, messageAsString: error.localizedDescription)
                    )
                }
            )
        }

I expect that given that self if used within the given callbacks. Am I right?

ibc added a commit that referenced this issue Apr 15, 2016
@ibc
Copy link
Collaborator Author

ibc commented Apr 15, 2016

@oNaiPs I've committed right now a fix following your suggestions, may you please check it? I've tested it and it does not crash. However I do not understand why I must pass [unowned self] here:

dispatch_async(self.queue) { [weak pluginRTCPeerConnection, unowned self] in
            pluginRTCPeerConnection!.close()

            // Remove the pluginRTCPeerConnection from the dictionary.
            self.pluginRTCPeerConnections[pcId] = nil
        }

At the end self points to the cordova CDVPlugin instance, do I miss something?

mark-veenstra added a commit to Mediapioniers/cordova-plugin-iosrtc that referenced this issue Apr 15, 2016
@oNaiPs
Copy link
Contributor

oNaiPs commented Apr 15, 2016

You;re right, you don't have to. CDVPlugin is not going to be deallocated anyways.

@mark-veenstra
Copy link
Contributor

We still encounter (sometimes) a crash in this close.

@jgsacris
Copy link

I have been testing this fix for a while on an iPhone 5 with 9.3.1 and it no longer crashed.

@ibc
Copy link
Collaborator Author

ibc commented Apr 25, 2016

Thanks @jgsacris

@ibc ibc closed this as completed Apr 25, 2016
@ibsus
Copy link

ibsus commented Sep 15, 2016

Unfortunately we are continuing to get a crash, even with the new code implemented. Same place as OP.

func RTCPeerConnection_close(command: CDVInvokedUrlCommand) {
    NSLog("iosrtcPlugin#RTCPeerConnection_close()")

    let pcId = command.argumentAtIndex(0) as! Int
    let pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]

    if pluginRTCPeerConnection == nil {
        NSLog("iosrtcPlugin#RTCPeerConnection_close() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
        return;
    }

    dispatch_async(self.queue) { [weak pluginRTCPeerConnection] in
        pluginRTCPeerConnection!.close() <!------ EXC_BREAKPOINT(code=1)

        // Remove the pluginRTCPeerConnection from the dictionary.
        self.pluginRTCPeerConnections[pcId] = nil
    }
}

Our configuration is as follows
iOS 9.3.5
Cordova ios 4.2.1

@mark-veenstra
Copy link
Contributor

@jpkolind We are also encountering same issue, but when we change the code as follows it works like a charm:

func RTCPeerConnection_close(command: CDVInvokedUrlCommand) {
    NSLog("iosrtcPlugin#RTCPeerConnection_close()")

    let pcId = command.argumentAtIndex(0) as! Int
    let pluginRTCPeerConnection = self.pluginRTCPeerConnections[pcId]

    if pluginRTCPeerConnection == nil {
        NSLog("iosrtcPlugin#RTCPeerConnection_close() | ERROR: pluginRTCPeerConnection with pcId=%@ does not exist", String(pcId))
        return;
    }

    dispatch_async(self.queue) { [weak pluginRTCPeerConnection] in
        // Needs extra check to avoid crash on the close
        if pluginRTCPeerConnection != nil {
            pluginRTCPeerConnection!.close()
        }

        // Remove the pluginRTCPeerConnection from the dictionary.
        self.pluginRTCPeerConnections[pcId] = nil
    }
}

@saghul
Copy link
Collaborator

saghul commented Sep 19, 2016

@mark-veenstra I think the crash can only happen if close it called twice. Since the actual close happens asynchronously, it's possible for close to be called twice and for the close to happen also on the Swift side. Now, if that happens, it's also possible that the first nil check is passed but the object becomes nil in the async block, so the fix LGTM. Can you please send a PR?

@ibsus
Copy link

ibsus commented Sep 19, 2016

Thank you! That worked perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants