Bug 27847 - Linked away exception on CallContext.LogicalGetData("SomeString") on device not simulator
Summary: Linked away exception on CallContext.LogicalGetData("SomeString") on device n...
Alias: None
Product: iOS
Classification: Xamarin
Component: Tools ()
Version: master
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Sebastien Pouliot
Depends on:
Reported: 2015-03-10 18:47 UTC by Ilya Basin
Modified: 2016-10-18 21:47 UTC (History)
8 users (show)

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

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Ilya Basin 2015-03-10 18:47:02 UTC
A call to CallContext.LogicalGetData("SomeString") fails on the device
with a "linked away" exception. This happens on the physical device (iPhone 6) but in the simulator(s) it works fine.

Exception message: System.NotSupportedException: Linked away

code snippet: var x = CallContext.LogicalGetData("SomeString");
Comment 1 Sebastien Pouliot 2015-03-10 22:16:03 UTC
The code to support remoting and/or multiple appdomain is largely removed (and unsupported [1]) on Xamarin.iOS.

You can re-enable (some part of) it by disabling the linker (not recommended) or by using the `--nolinkaway` [2] in the Additional mtouch arguments (of the project options). That later option has a smaller impact (size wise) but it still has limitations (i.e. you won't have _Link away_ exceptions but not everything feature works, YMMV).

[1] http://developer.xamarin.com/guides/ios/advanced_topics/limitations/
[2] https://spouliot.wordpress.com/2011/11/01/linker-vs-linked-away-exceptions/
Comment 2 Ilya Basin 2015-03-10 23:56:29 UTC
I am not using CallContext.LogicalGetData for remoting. I use it to create thread static variables that persist across asynchronous calls. This is a valid use, I think. There has to be a mechanism for that.

If there is a better/proper way to do it differently, please let me know. Maybe I am missing something.

Thank you in advance.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2015-03-11 04:37:34 UTC
You can create thread-static variables using the ThreadStaticAttribute:

class MyClass {
    static object MyObject;
Comment 4 Marek Safar 2015-03-11 06:09:03 UTC
Sadly CallContext is always removed by linker (for historical reason someone was too aggressive by removing it). 

Best approach is to avoid it and pass the context as an argument to your async call. This can require some work if you are doing very deep calls but it's recommended as your data can be more strongly typed than with CallContext and the code is usually easier to follow than using CallContext.
Comment 5 Sebastien Pouliot 2015-03-11 08:29:24 UTC

> There has to be a mechanism for that.

There is. As noted (comment #1) you can disable this using --nolinkaway (and if it's not remoting related then will work, i.e. the managed code will be present but remoting features won't be part of the mono runtime).

There are also alternatives, as noted in comments #3 and #4, to achieve the same.
Comment 6 Ilya Basin 2015-03-11 09:45:40 UTC
[ThreadStatic] will not persist after an await, so it won't work for this.

Would it be possible to change the linker behavior for CallContext.LogicalGetData and CallContext.LogicalSetData? 

Having to do something that is unsupported (even if can be achieved by  linker settings) is risky. 

Needing to create an ambient variable (thread-specific variable) that does not need to be passed through but will persist across calls is very important in many cases. For example for for creating frameworks. Such an approach is used by Microsoft for example when implementing:

1) Transaction scope
using (new TransactionScope())
    //Code here is all part of the same transaction, transaction is kept in an ambient variable that is 
    //put there by the TransactionScope constructor while IDisposable implementation cleans up 
    //and (possibly) completes the transaction.

2) HttpContext in ASP.NET
HttpContext can be accessed to access Request and other context variables while processing an HTTP request.

Having to pass the context as a parameter every time is not always a good option. For example it is not a good option when developing a framework because you do not want to force your users to pass extraneous variables into their methods. Also it is not very convenient for deep calls.

I think it would be great if you would reconsider linking it away and support it.

Comment 7 Ilya Basin 2015-03-11 10:07:45 UTC
Also, I don't have an Android device to try it on, could you please tell me if this is going to be a problem on Android as well?

Thank you.
Comment 8 Jahmai 2015-06-29 00:05:40 UTC
We use this for transferring diagnostics contextual information between async calls such as logical call stack.

Since we're not using it for remoting, is there any way to preserve logical call context without using --nolinkaway which is excessive.
Comment 9 Thomas van der Heijden 2015-11-24 22:51:51 UTC
I ran into this problem as well.  Am I correct in assuming that Xamarin does not support CallContext.LogicalGetData and CallContext.LogicalSetData?
Comment 10 Shawn 2016-10-16 17:11:10 UTC
Any progress on this request?
Comment 11 Sebastien Pouliot 2016-10-18 21:47:59 UTC
Features related to remoting is not supported by XI as most of them requires dynamic/code generation which is not possible under full AOT.

There are workarounds, documented in comment #5, including one which cancel the removal of (mostly) dead code. That allow `CallContext.Logical[Get|Set]Data` to work at the cost of larger executables.