EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Jean Suisse
Dear All,

I wrote a small benchmark Swift Application to test line drawing using CG API.

The app contains a custom NSView, which is responsible of holding the data & displaying them for the purpose of the test.
At launch, the application dispatches two closures to a concurrent queue. One requests a curve from the view [.xyCurve()] generates data points randomly, adds them to the view’s internal data source [appendPoint]. The other just very roughly measures the number of points per second graphed by the system in the test conditions.

Internally, the view uses NSLocks to:

– Ensure no points are added or removed while the view is refreshing (the view manages its data source and only keeps the N=1000 last data points)

– Ignore any [reloadData()] requests as long as the last request hasn’t been performed. As a result, the view does not refresh every time a point is added.

When the App is launched, I randomly get a EXC_I386_GPFLT error. Sometimes after a few seconds, sometimes after more than a minute.

Stack trace is always:

0: libswiftCore.dylib`usesNativeSwiftReferenceCounting_unowned(void const*):
1: libswiftCore.dylib`swift_unknownRetainUnowned:
2: MyApp.AppDelegate(applicationDidFinishLaunching(MyApp.AppDelegate)->(Objective.C.NSNotification)->()).(closure#1)
3:libdispatch.dylib`_dispatch_call_block_and_release:

Any suggestion on how to debug this?

Best Regards,
Jean






@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

@IBOutlet weak var window: NSWindow!
@IBOutlet weak var smallGraphicView: JSSmallGraphicView!

var i: UInt64 = 0

func applicationDidFinishLaunching(aNotification: NSNotification)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
{
[unowned self] in
usleep(2000000)
var curve = self.smallGraphicView.xyCurve()

for (self.i = 1; self.i < UInt64.max-1; self.i++)
{
self.smallGraphicView.appendPoint(JSDataPoint(CGFloat(self.i) * 1E-15, CGFloat(random()) * -1E-15), toCurve: curve)
self.smallGraphicView.reloadData()
}
}

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
{
[unowned self] in

while(true)
{
let startI = self.i
usleep(1000000)
let endI = self.i

print("\(endI-startI) pps\n")
}
}

}

func applicationWillTerminate(aNotification: NSNotification)
{
// Insert code here to tear down your application
}
}

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/45966BD2-9B87-4132-9D99-C62BA10E55D3%40gmail.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Justin Kolb
From my experience this is due to usage of unowned self. You have to be 200% sure your block will outlive self or you will get this crash. It is usually better to use weak self in you blocks and then do "if let strongSelf = self {" and do your work inside this if statement using strongSelf instead of self. This guarantees that if you are inside the "if" the self will be kept alive by the strong reference. This tip applies to Objective-C also.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/45f6ecdc-8d6f-4158-a913-fa306075ed8d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Jean Suisse
I did add a deinit method to the AppDelegate, the JSSmallGraphicView and to JS2DPoint. These are the three classes involved in the loop.
As expected, none of the deinit method is called before the crash BUT removing [unowned self] in at the beginning of the closures unexpectedly solves the issue…

The test project still crashes under Xcode 7.0 beta 4. So if there’s a bug, it’s still there. But I need to be sure before reporting it.




On 20 août 2015, at 03:25, Justin Kolb <[hidden email]> wrote:

The error you provided definitely points to Swift internal functions that are called when unowned references are used. There have been reported cases of unowned being buggy in older versions of Swift. I usually debug these kind of issues by putting a breakpoint in the deinit method of the object I think is getting dealloced. But if this is a compiler bug there might not be much you can do. I would still strongly suggest against using unowned in most code, especially if multiple threads are involved.

On Aug 19, 2015, at 7:10 PM, Jean Suisse <[hidden email]> wrote:

In my case, self refers to the AppDelegate instance. It should live as long as the app is running, so I shouldn’t get this crash.
How can I investigate this?



On 20 août 2015, at 02:03, Justin Kolb <[hidden email]> wrote:

From my experience this is due to usage of unowned self. You have to be 200% sure your block will outlive self or you will get this crash. It is usually better to use weak self in you blocks and then do "if let strongSelf = self {" and do your work inside this if statement using strongSelf instead of self. This guarantees that if you are inside the "if" the self will be kept alive by the strong reference. This tip applies to Objective-C also.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/45f6ecdc-8d6f-4158-a913-fa306075ed8d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/F530C405-1F56-4063-BD13-0B3109CE7539%40gmail.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Ken Ferry
Would it be possible to show the full project? This sounds more like an issue with unsafe threading in the test app than a Swift issue. 

For example, if setNeedsDisplay is not legal on a background thread. 

-ken



On Wed, Aug 19, 2015 at 7:16 PM, Jean Suisse <[hidden email]> wrote:

I did add a deinit method to the AppDelegate, the JSSmallGraphicView and to JS2DPoint. These are the three classes involved in the loop.
As expected, none of the deinit method is called before the crash BUT removing [unowned self] in at the beginning of the closures unexpectedly solves the issue…

The test project still crashes under Xcode 7.0 beta 4. So if there’s a bug, it’s still there. But I need to be sure before reporting it.




On 20 août 2015, at 03:25, Justin Kolb <[hidden email]> wrote:

The error you provided definitely points to Swift internal functions that are called when unowned references are used. There have been reported cases of unowned being buggy in older versions of Swift. I usually debug these kind of issues by putting a breakpoint in the deinit method of the object I think is getting dealloced. But if this is a compiler bug there might not be much you can do. I would still strongly suggest against using unowned in most code, especially if multiple threads are involved.

On Aug 19, 2015, at 7:10 PM, Jean Suisse <[hidden email]> wrote:

In my case, self refers to the AppDelegate instance. It should live as long as the app is running, so I shouldn’t get this crash.
How can I investigate this?



On 20 août 2015, at 02:03, Justin Kolb <[hidden email]> wrote:

From my experience this is due to usage of unowned self. You have to be 200% sure your block will outlive self or you will get this crash. It is usually better to use weak self in you blocks and then do "if let strongSelf = self {" and do your work inside this if statement using strongSelf instead of self. This guarantees that if you are inside the "if" the self will be kept alive by the strong reference. This tip applies to Objective-C also.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/45f6ecdc-8d6f-4158-a913-fa306075ed8d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/F530C405-1F56-4063-BD13-0B3109CE7539%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/1440083351374.ddf3ea83%40Nodemailer.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: EXC_I386_GPFLT in usesNativeSwiftReferenceCounting_unowned

Jean Suisse
Dear Ken,

I boiled everything down to small working example. You can try to run the program several times. Usually, the issue appears after less than 30 seconds. It is random, thus most probably a race condition. I can’t figure it out though.

The app contains a custom view (JSSmallGraphicView) that owns a JS2DCurve containing data points (XY pairs). When the “test” button is clicked, the app runs two closures in global queues from the app delegate :

One requests the view to add points to the curve, then to redraw endlessly. The other one just computes how many redraw are made per second.

Redraws are requested by calling JSSmallGraphicView.reloadData(), which only invokes setNeedsDisplayInRect (on the main thread) if a redraw has not already been requested.
The view uses lock to protect accessing the curve to add points or to draw on screen and to protect the redrawRequested flag.

The app is just to benchmark a few parameters and should look like this:

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/DEA50B53-AB6B-4A0E-89A9-3E6C820613CB%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


And some time after hitting the test button, the following error should appear:

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/DEA50B53-AB6B-4A0E-89A9-3E6C820613CB%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Best regards,
Jean

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/DEA50B53-AB6B-4A0E-89A9-3E6C820613CB%40gmail.com.
For more options, visit https://groups.google.com/d/optout.



On 20 août 2015, at 17:09, Ken Ferry <[hidden email]> wrote:

Would it be possible to show the full project? This sounds more like an issue with unsafe threading in the test app than a Swift issue. 

For example, if setNeedsDisplay is not legal on a background thread. 

-ken



On Wed, Aug 19, 2015 at 7:16 PM, Jean Suisse <[hidden email]> wrote:

I did add a deinit method to the AppDelegate, the JSSmallGraphicView and to JS2DPoint. These are the three classes involved in the loop.
As expected, none of the deinit method is called before the crash BUT removing [unowned self] in at the beginning of the closures unexpectedly solves the issue…

The test project still crashes under Xcode 7.0 beta 4. So if there’s a bug, it’s still there. But I need to be sure before reporting it.




On 20 août 2015, at 03:25, Justin Kolb <[hidden email]> wrote:

The error you provided definitely points to Swift internal functions that are called when unowned references are used. There have been reported cases of unowned being buggy in older versions of Swift. I usually debug these kind of issues by putting a breakpoint in the deinit method of the object I think is getting dealloced. But if this is a compiler bug there might not be much you can do. I would still strongly suggest against using unowned in most code, especially if multiple threads are involved.

On Aug 19, 2015, at 7:10 PM, Jean Suisse <[hidden email]> wrote:

In my case, self refers to the AppDelegate instance. It should live as long as the app is running, so I shouldn’t get this crash.
How can I investigate this?



On 20 août 2015, at 02:03, Justin Kolb <[hidden email]> wrote:

From my experience this is due to usage of unowned self. You have to be 200% sure your block will outlive self or you will get this crash. It is usually better to use weak self in you blocks and then do "if let strongSelf = self {" and do your work inside this if statement using strongSelf instead of self. This guarantees that if you are inside the "if" the self will be kept alive by the strong reference. This tip applies to Objective-C also.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/45f6ecdc-8d6f-4158-a913-fa306075ed8d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/F530C405-1F56-4063-BD13-0B3109CE7539%40gmail.com.
For more options, visit https://groups.google.com/d/optout.



--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/1440083351374.ddf3ea83%40Nodemailer.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Swift Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/swift-language/DEA50B53-AB6B-4A0E-89A9-3E6C820613CB%40gmail.com.
For more options, visit https://groups.google.com/d/optout.

PastedGraphic-3.png (53K) Download Attachment
PastedGraphic-2.png (847K) Download Attachment
SANDBOX_test.zip (112K) Download Attachment