Bug 18865 - WeakReference.TryGetTarget behavior is incorrect
Summary: WeakReference.TryGetTarget behavior is incorrect
Status: NEW
Alias: None
Product: Runtime
Classification: Mono
Component: GC (show other bugs)
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-04-08 14:11 UTC by Jon Goldberger [MSFT]
Modified: 2014-09-14 09:03 UTC (History)
7 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test Project (33.07 KB, application/zip)
2014-04-08 14:11 UTC, Jon Goldberger [MSFT]
Details

Comment 1 Jon Goldberger [MSFT] 2014-04-08 14:11:54 UTC
From case:

We're using the latest Xamarin.iOS, and we're encountered a bug with the WeakRefence<T>.TryGetValue(), which returns an invalid value (true in this case), even if the target object has been collected.

Attached is a sample iOS application to demonstrate the issue, as well as a WPF application for the correct behavior.
Comment 3 Jon Goldberger [MSFT] 2014-04-08 14:13:27 UTC
I observed the same behavior loading the code into an iOS project in Xamarin Studio on the Mac.
Comment 5 Zoltan Varga 2014-04-10 17:15:04 UTC
I can't reproduce this, the test app prints:
ALIVE 0 on <n>, but TryGetTarget tell 0 on <n>
which I think is the correct behavior.
Comment 6 Andrei.N 2014-09-14 09:03:35 UTC
This is from Xamarin’s WeakReference<T>:

public bool TryGetTarget (out T target)
{
    if (!this.handle.IsAllocated) {
        target = (T)((object)null);
        return false;
    }
    target = (T)((object)this.handle.Target);
    return target != null;
}

Isn’t it an issue that it first checks if it’s allocated and if it is, it THEN gets a reference to it?

Isn't it possible that between the two operations the garbage collector could reclaim the target?

Wouldn't be correct to write instead

public bool TryGetTarget (out T target)
{
    target = (T)((object)this.handle.Target);
    if (!this.handle.IsAllocated) {
        target = (T)((object)null);
    }
    return target != null;
}

Note You need to log in before you can comment on or make changes to this bug.