AdRotator v0.4 XNA cross thread access issue.

Nov 12, 2012 at 4:57 PM

It occurred once so far, but here is the trace. I hope that helps.

> System.Windows.dll!MS.Internal.XcpImports.CheckThread() + 0x21 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValueInternal(System.Windows.DependencyProperty dp) + 0x13 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValue(System.Windows.DependencyProperty dp) + 0x2 bytes   System.Windows.dll!System.Windows.Deployment.EntryPointAssembly.get()   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.SetExceptionMessagesCulture() + 0x5 bytes   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.AdManager() + 0x1c bytes   Microsoft.Advertising.Mobile.Xna.dll!Microsoft.Advertising.Mobile.Xna.AdGameComponent.Initialize(Microsoft.Xna.Framework.Game game, string applicationId) + 0x18 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.CreatePubCentertAdControl() + 0x18 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Invalidate(bool selectNextAdType) + 0x16c bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.OnAdLoadFailed(AdRotator.Model.AdType adType) + 0x33 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Current_MobFox_AdLoadingFailed(object sender, System.EventArgs e) + 0x1d bytes   AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetAdWebResponse.AnonymousMethod__0(string IPsource, System.Exception IPex) + 0x50 bytes   AdRotatorXNA.dll!AdRotator.Networking.Network.GetDeviceIP.AnonymousMethod__3(System.IAsyncResult r) + 0xbd bytes   System.Windows.dll!System.Net.Browser.ClientHttpWebRequest.InvokeGetResponseCallback.AnonymousMethod__8(object state2) + 0x1b bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.WaitCallback_Context(object state) + 0x18 bytes   mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x63 bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.doWork(object o) + 0x47 bytes   mscorlib.dll!System.Threading.Timer.ring() + 0x70 bytes

Nov 12, 2012 at 9:49 PM

Another one

> System.Windows.dll!MS.Internal.XcpImports.CheckThread() + 0x21 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValueInternal(System.Windows.DependencyProperty dp) + 0x13 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValue(System.Windows.DependencyProperty dp) + 0x2 bytes   System.Windows.dll!System.Windows.Deployment.EntryPointAssembly.get()   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.SetExceptionMessagesCulture() + 0x5 bytes   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.AdManager() + 0x1c bytes   Microsoft.Advertising.Mobile.Xna.dll!Microsoft.Advertising.Mobile.Xna.AdGameComponent.Initialize(Microsoft.Xna.Framework.Game game, string applicationId) + 0x18 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.CreatePubCentertAdControl() + 0x18 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Invalidate(bool selectNextAdType) + 0x16c bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.OnAdLoadFailed(AdRotator.Model.AdType adType) + 0x33 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Current_MobFox_AdLoadingFailed(object sender, System.EventArgs e) + 0x1d bytes   AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__5(Microsoft.Xna.Framework.Graphics.Texture2D s, System.Exception e) + 0x3b bytes   AdRotatorXNA.dll!AdRotatorXNA.Helpers.ImageDownload.GetImageFromURL(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics, string imageUrl, System.Action<Microsoft.Xna.Framework.Graphics.Texture2D,System.Exception> callback) + 0x33 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__4(System.Collections.Generic.List<AdRotator.Networking.AdWebResponse> results, System.Exception ex) + 0x73 bytes   AdRotatorXNA.dll!AdRotator.Networking.AdWebRequest.ReadMobFoxAdResponse.AnonymousMethod__8(string results, System.Exception ex) + 0xa1 bytes   AdRotatorXNA.dll!AdRotator.Networking.Network.GetStringFromURL.AnonymousMethod__0(System.IAsyncResult r) + 0x39 bytes   System.Windows.dll!System.Net.Browser.ClientHttpWebRequest.InvokeGetResponseCallback.AnonymousMethod__8(object state2) + 0x1b bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.WaitCallback_Context(object state) + 0x18 bytes   mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x63 bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.doWork(object o) + 0x47 bytes   mscorlib.dll!System.Threading.Timer.ring() + 0x70 bytes

Coordinator
Nov 13, 2012 at 9:41 AM

Can you please provide some details for which version of AdRotator you are using, which platform.

By the looks of it you are using the XNA version and we did find a critical bug in the 0.3 release with pubcenter, please check you are using the latest version.

Nov 13, 2012 at 10:10 AM
Edited Nov 13, 2012 at 10:16 AM

As I wrote in the topic 'AdRotator V0.4 for xna' I downloaded it yesterday and encountered the issue four times during a evening of testing.

I also encountered

* the 'pubcenter' adds draw at their original location error (which I have never seen when I use pubcenter directly).

* No ad's showing up at all even with both a default texture set and a default ad in the xml.

Coordinator
Nov 13, 2012 at 10:21 AM

LOL, apologies didn't see that.

The pubcenter is a known one and we're looking in to it.

Not sure about the default house ad issue as that is working fine in the examples but will look into it.

 

If you find any more details let me know, would be a great help if you try downloading the source and reference that instead of the dll in testing to see if you can replicate the stack trace issue.  Seems to be threading related but cannot see a root cause.

One other note are you using this in the 7.1.1 SDK or the WP8 SDK (as WP7.1)?

Nov 13, 2012 at 10:33 AM

It's fairly easy to reproduce apparently. Took me less than 2 min of testing after I downloaded the source.

  System.Windows.dll!MS.Internal.XcpImports.CheckThread() + 0x21 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValueInternal(System.Windows.DependencyProperty dp) + 0x13 bytes   System.Windows.dll!System.Windows.DependencyObject.GetValue(System.Windows.DependencyProperty dp) + 0x2 bytes   System.Windows.dll!System.Windows.Deployment.EntryPointAssembly.get()   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.SetExceptionMessagesCulture() + 0x5 bytes   Microsoft.Advertising.Mobile.dll!Microsoft.Advertising.AdManager.AdManager() + 0x1c bytes   Microsoft.Advertising.Mobile.Xna.dll!Microsoft.Advertising.Mobile.Xna.AdGameComponent.Initialize(Microsoft.Xna.Framework.Game game, string applicationId) + 0x18 bytes > AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.CreatePubCentertAdControl() Line 1447 + 0x1a bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Invalidate(bool selectNextAdType) Line 920 C#  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.OnAdLoadFailed(AdRotator.Model.AdType adType) Line 1176 C#  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Current_Smaato_AdLoadingFailed(object sender, string ErrorCode, string ErrorDescription) Line 1685 + 0x7 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdSmaatoComponent.LoadContent() Line 118 + 0x16 bytes C#  Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.DrawableGameComponent.Initialize() + 0xb8 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdSmaatoComponent.Initialize() Line 78 + 0x6 bytes C#  Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.Game.GameComponentAdded(object sender, Microsoft.Xna.Framework.GameComponentCollectionEventArgs e) + 0x13 bytes   Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.GameComponentCollection.OnComponentAdded(Microsoft.Xna.Framework.GameComponentCollectionEventArgs eventArgs) + 0x15 bytes   Microsoft.Xna.Framework.Game.dll!Microsoft.Xna.Framework.GameComponentCollection.InsertItem(int index, Microsoft.Xna.Framework.IGameComponent item) + 0x2c bytes   mscorlib.dll!System.Collections.ObjectModel.Collection<Microsoft.Xna.Framework.IGameComponent>.Add(Microsoft.Xna.Framework.IGameComponent item) + 0x28 bytes   AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Invalidate(bool selectNextAdType) Line 955 + 0x16 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.OnAdLoadFailed(AdRotator.Model.AdType adType) Line 1176 C#  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Current_MobFox_AdLoadingFailed(object sender, System.EventArgs e) Line 1648 + 0x7 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__5(Microsoft.Xna.Framework.Graphics.Texture2D s, System.Exception e) Line 212 + 0x1b bytes C#  AdRotatorXNA.dll!AdRotatorXNA.Helpers.ImageDownload.GetImageFromURL(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics, string imageUrl, System.Action<Microsoft.Xna.Framework.Graphics.Texture2D,System.Exception> callback) Line 17 + 0x12 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__4(System.Collections.Generic.List<AdRotator.Networking.AdWebResponse> results, System.Exception ex) Line 205 + 0x2d bytes C#  AdRotatorXNA.dll!AdRotator.Networking.AdWebRequest.ReadMobFoxAdResponse.AnonymousMethod__8(string results, System.Exception ex) Line 80 + 0xd bytes C#  AdRotatorXNA.dll!AdRotator.Networking.Network.GetStringFromURL.AnonymousMethod__0(System.IAsyncResult r) Line 26 + 0xd bytes C#  System.Windows.dll!System.Net.Browser.ClientHttpWebRequest.InvokeGetResponseCallback.AnonymousMethod__8(object state2) + 0x1b bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.WaitCallback_Context(object state) + 0x18 bytes   mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x63 bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.doWork(object o) + 0x47 bytes   mscorlib.dll!System.Threading.Timer.ring() + 0x70 bytes

Nov 13, 2012 at 10:35 AM

I am using the latest one for WP7 since I didn't move to WP8.

So thats probably 7.1.1 :)

Coordinator
Nov 13, 2012 at 10:39 AM

OK, so when you were running it attached to the source at what point did it break?

File / line number

And do you have a copy of your config XML you cn attach so I can test using your config?

Nov 13, 2012 at 10:46 AM
Edited Nov 13, 2012 at 10:46 AM

A quick glance on the code seem to indicate there is little control of which thread you are doing things from.

To quickly fix errors like this it might help to tag your objects during constructions with the thread they belong to and then do a assertion check to verify that you are in the correct thread as the first thing in all member methods of each object.

.net's async callbacks are very dangerous to work with since they quite often get called from a 'random' thread and things will just fuck up from there if nothing is done to protect the code.

Nov 13, 2012 at 10:50 AM

I basically started the emulator. Then started the app, if nothing crashed, stopped and tried again. Four tries was what it took.

It stopped at AdRotatorXNA.cs line 1447 -> if (!AdGameComponent.Initialized) AdGameComponent.Initialize(this.Game, PubCenterAppId);

You an get my configuration file here ->

http://manabattery.com/AdInfo/defaultAdSettings.xml 

Since I am in DK I should be hitting the default configuration.

Nov 13, 2012 at 11:02 AM
Edited Nov 13, 2012 at 11:10 AM

Just to do some quick debugging on my own I did the following modifications to AdRotatorXNAComponent

Added a 

    private int m_threadId;

In the constructor I added

      m_threadId = System.Threading.Thread.CurrentThread.ManagedThreadId;

Then I added the following method

    private void CheckThread()    {      Debug.Assert(m_threadId == System.Threading.Thread.CurrentThread.ManagedThreadId);    }

And called that as the first thing in every method (basically I did what I recommended above).

 

I then triggered the error again and this is the trace.

So Current_MobFox_AdLoadingFailed gets called from a 'random' thread and things will start to degrade from there.

So you most likely need to ensure that the method Current_MobFox_AdLoadingFailed 'defers' the call to the correct thread.

  AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.CheckThread() Line 574 + 0x17 bytes C#> AdRotatorXNA.dll!AdRotatorXNA.AdRotatorXNAComponent.Current_MobFox_AdLoadingFailed(object sender, System.EventArgs e) Line 1700 + 0x6 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__5(Microsoft.Xna.Framework.Graphics.Texture2D s, System.Exception e) Line 212 + 0x1b bytes C#  AdRotatorXNA.dll!AdRotatorXNA.Helpers.ImageDownload.GetImageFromURL(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphics, string imageUrl, System.Action<Microsoft.Xna.Framework.Graphics.Texture2D,System.Exception> callback) Line 17 + 0x12 bytes C#  AdRotatorXNA.dll!AdRotatorXNA.AdMobFoxComponent.GetMobFoxAd.AnonymousMethod__4(System.Collections.Generic.List<AdRotator.Networking.AdWebResponse> results, System.Exception ex) Line 205 + 0x2d bytes C#  AdRotatorXNA.dll!AdRotator.Networking.AdWebRequest.ReadMobFoxAdResponse.AnonymousMethod__8(string results, System.Exception ex) Line 80 + 0xd bytes C#  AdRotatorXNA.dll!AdRotator.Networking.Network.GetStringFromURL.AnonymousMethod__0(System.IAsyncResult r) Line 26 + 0xd bytes C#  System.Windows.dll!System.Net.Browser.ClientHttpWebRequest.InvokeGetResponseCallback.AnonymousMethod__8(object state2) + 0x1b bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.WaitCallback_Context(object state) + 0x18 bytes   mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x63 bytes   mscorlib.dll!System.Threading.ThreadPool.WorkItem.doWork(object o) + 0x47 bytes   mscorlib.dll!System.Threading.Timer.ring() + 0x70 bytes

I hope that helps a bit.

Also as a general principle when doing threaded development its a very good idea to tag your objects and verify the thread with at least a assert to ensure no threading errors sneak into the code.

Nov 13, 2012 at 11:17 AM

I looked a bit more at the code and its probably your helper method Network.GetStringFromURL where you never intended the callback to execute from any other thread than the calling one.

Now unfortunately BeginGetResponse does execute code on another thread so the callback gets called from it.

Coordinator
Nov 13, 2012 at 11:54 AM

Hmm, I thought I had handled that by forcing Invalidate to always be called on the Main UI thread, that was the main reason for the 0.4 update.  Hmm.

I noted this behavior from the PubCenter AdControl which seems to still do Silverlight things under the hood in the XNA version, for some reason it will only generate an Ad if on the Main UI thread.  First few patches didn't work so I moved running Invalidate to always be called on the Main UI thread with a System.Dispatcher.

If you want to see if you can resolve the issue and submit a working patch then that would be very helpful, finding time too look into this at present is tricky ;-(

Nov 13, 2012 at 2:41 PM

Yeah I have the same time issue, which incidental was why I looked at this library to begin with :)

I will try to take a look but my initial look at the code did spot quite a few possible threading errors.

Now personally when working with threads I tend to err on the side of caution so the patch would probably be quite extensive.

Coordinator
Nov 13, 2012 at 2:49 PM

Well were always looking for additional contributors, so if you don't mind rolling your sleeves up and joining in let us know.

Coordinator
Nov 25, 2012 at 2:18 PM

Any update whether you can help out or just send us a list of suggestions and we'll see if we can get them implemented?