Closed MaximG1234 closed 4 years ago
@MaximG1234 what does your HOCON look like? Because otherwise, there's nothing that should really block there at all, most of the components all start asynchronously.
Haha, thats about the quickest response I've seen on Github. Thanks Aaron. Give me a minute to work out how do get the hocon output in VS.
My apologies. I misunderstood your question. I thought you were talking about the phone debug output.
My akka config file looks like this.
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = ""remote""
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
dot-netty.tcp {
transport-protocol = tcp
hostname = localhost
}
}
}
I have tried using hostname 0.0.0.0 and am injecting the config directly using the constructor overload.
I have also moved the code from the onStart location in the Android app to event handlers and the results are the same.
I have also tried using both the Android emulator and a real device.
However I note that all of these results are from 1 PC running Visual Studio Enterprise 2019 so it is possible its somehow isolated to my machine. I dont have another machine to test on.
@MaximG1234
Ok so this is going to sound dumb, but give it a try:
provider = ""remote""
Change this to
provider = remote
My code was:
var config = ConfigurationFactory.ParseString(@"
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = ""remote""
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
dot-netty.tcp {
transport-protocol = tcp
hostname = localhost
}
}
}
");
CHANGED TO:
var config = ConfigurationFactory.ParseString(@"
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = remote
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
dot-netty.tcp {
transport-protocol = tcp
hostname = localhost
}
}
}
");
Same result...
Hmmm... And with the debugger attached, no exceptions get thrown? Wondering if Akka.Remote binding to an inbound socket is the problem here - not sure if that's permitted on Xamarin apps.
https://www.dropbox.com/s/qc7z6jt9pjq61i6/2019-11-21%2004-29-33.mkv?dl=0
See for yourself ^
Gonna try one last thing for today which is creating a native (i.e. without xamarin.forms) project and seeing what happens.
Can confirm, same behaviour using Xamarin native.
If you turn off Akka.Remote altogether, does it start up?
Removed all references to Akka.Remote and used akka {} as config file and same result. Emulator doing the same thing too.
Android 9.0 API 28
In that case, it means it's an issue with either the HOCON parser or a non-ActorRefProvider
component (i.e. EventStream
) not loading up properly. My money is on the HOCON parser, which we're due to replace with the stand-alone HOCON library in this Github organization as part of the v1.4.0 final release.
If I go back to (without the references)
akka {
log-config-on-start = on
stdout-loglevel = DEBUG
loglevel = DEBUG
actor {
provider = ""remote""
debug {
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
dot-netty.tcp {
hostname = localhost
}
}
}
I get the error 'Akka.Configuration.ConfigurationException: ''akka.actor.provider' is not a valid type name : 'Akka.Remote.RemoteActorRefProvider, Akka.Remote''' - as expected. If that helps...
I might load up the akka source tomorrow myself. I'll let you know any results. Thanks for your help!
Hi @MaximG1234
I've followed your steps and haven't been able to reproduce the issue. Everything works fine for me on OSX using the exact same setup.
However, I don't have the MockDataStore
, or InitializeComponent
that is shown in your video. Perhaps there is something within that code which is blocking. During the hang, it might help to pause the debugger and view the current threads to see what code is currently executing.
I have attached the Akka source directly to an example project. The issue is occuring here:
Line 175 Akka.Event.LoggingBus -> AddLogger
askTask.Result blocks:
try
{
response = askTask.Result;
}
catch (Exception ex) when (ex is TaskCanceledException || ex is AskTimeoutException)
{
Publish(new Warning(loggingBusName, GetType(),
string.Format("Logger {0} [{2}] did not respond within {1} to InitializeLogger(bus)", loggerName, timeout, loggerType.FullName)));
}
The status of askTask is Status = WaitingForActivation
https://www.dropbox.com/s/bywt6cx6k5ejutq/akka.JPG
I am currently in the process of starting up a VM to confirm this is not somehow isolated to my machine.
This looks like a runtime problem - that task should time out after 5 seconds by default, but it also shouldn't time out period because by default the only logger we load is the built-in one that writes out to the console.
We saw this sometimes with older versions of .NET Framework - weird TaskCompletionSource
behavior that we had to work around using some scheduling hacks and so on. I'm not a Xamarin user, so could you please tell us which version of the runtime you're targeting in it? I.e. a specific Mono version, Android version, etc...
OK I have now tested on a VM and 100% confirmed reproducible bug.
Android version is 9 API version is 28. I havent tested other versions yet. The Mono.Android.dll referenced is as follows: 10.0.6.2; git-rev-head;c407838; git-branch:d16-3
Attached you will find an example project which reproduces the error.
Do you know which Mono version is being used?
How do I determine that? I thought it was based on the dll Mono.Android.dll?
Looking at your XML in the projects, looks like MonoAndroid9.0
Sorry, I'm not much of a Xamarin user here - always wanted to learn how but never had a great project for it :p - you'll have to bear with some of my newbie questions while we dig into it.
@MaximG1234
I don't have a Windows machine available right now, but Visual Studio on Mac shows the Mono runtime here by looking at the application settings:
Next time I'm on Windows I'll have a look for where the Mono version is specified.
@Aaronontheweb MonoAndroid9.0 sounds like a bridging library, the highest Mono version right now is 6.4.0 I think.
@Aaronontheweb No worries at all, just grateful that you guys are investigating. This was actually supposed to be my first mobile app but..... :-( lol
@nagytech I am still having trouble determining my version of Mono, I see nowhere in Visual Studio where a version number for Mono is shown and I have tried getting the value using this technique which also seems to be failing (returning null value, looks like method GetDisplayName doesnt exist) .
Far out, think I finally found it. I believe I was correct in that Mono.Android.dll determines your Mono Version. Microsoft really doesn't seem to make things easy....
"Issues fixed in Xamarin.Android 10.0.6.2 Application Mono Framework behavior on device and emulator This version of Xamarin.Android updates the Mono 6.4 runtime and class libraries from Commit 5608fe0a to Commit 476d72b9, adding 7 new commits."
https://docs.microsoft.com/en-us/xamarin/android/release-notes/10/10.0
@MaximG1234
I've been able to run the code you sent, but something odd is happening.
On first startup, everything loads fine. But, if I stop the debugger and run it again I am able to reproduce your issue.
Clearing the app cache, force stopping the app, or even uninstalling it won't release the block. Only after shutting down the emulator can I run the application again just fine. But, the second run will always hang.
To me it sounds like a file or resource lock isn't being released when the Xamarin app exits.
If I run adb shell ps
before starting up the app, the first time I get:
...
system 4008 1685 1447068 70148 0 0 S com.android.keychain
u0_a85 4166 1685 1447608 69356 0 0 S Mono.Android.DebugRuntime
And when the app is started the first time, I see:
...
u0_a85 4166 1685 1447864 68996 0 0 S Mono.Android.DebugRuntime
u0_a22 4229 1685 1447824 76048 0 0 S com.android.defcontainer
u0_a88 4318 1685 1564528 144488 0 0 S com.companyname.app1
Then, when I kill the app, clear the cache and uninstall it I see:
...
u0_a22 6948 1683 1447312 69008 0 0 S com.android.defcontainer
...
So I think there's something locked or blocked by com.android.defcontainer
. Let me have a deeper look and see what's going on.
@nagytech My bad, I think I might have uploaded a crappy version of my code. Check the file ItemsViewModel in the project and remove the try catch block. Thats probably what is causing your behaviour
@nagytech After downgrading the project to version 6 of Android I was able to reproduce the intermittent behaviour you describe
@MaximG1234
Looking into the com.android.defcontainer
process didn't really uncover anything.
Out of interest, I decided to start up the ActorSystem in a different thread. And, I've not seen the application lock up yet.
protected override void OnStart()
{
Task.Run(() =>
{
var s = ActorSystem.Create("client1", ConfigurationFactory.Empty);
s.Log.Info("Asdf");
});
}
So, this leads me to believe that the issue may not be in Akka.NET, but more the thread context which executes the OnStart()
method. I'll keep trying to find out more, but the async startup should work for you in the meantime.
@nagytech Absolute legend. Thanks heaps!
Can confirm this appears to work both in the VS 2019 Android emulator and on my device. Disappointed that I didn't try just running the code in a new thread.
Is there any reason why using the exact code above could cause any issues in the Akka communications? Would the above code be fine to use in production?
@MaximG1234
It's been a long time since I've done any Xamarin development, so I can't say for certain what the best approach would be. From what I recall, it's possible for the OnStart()
method to be called multiple times so you might be best to try and instantiate the ActorSystem using a DI framework.
@nagytech Thanks again for your help!
@Aaronontheweb Just wanted to give you a quick update.
I can confirm that the above solution does successfully work and have now successfully tested a mobile connection and transmitting data.
However, I have found what is likely another possibly related bug. Basically it looks like dispatcher = akka.actor.synchronized-dispatcher isn't being honoured in my application.
I've got some code that looks like this:
public void HandleTablesResponse(IEnumerable<Table> allTables)
{
this.DisplayAlert("Alert", $"{allTables.Count()} total tables", "cancel");
}
I have successfully been able to get it to work in my WPF app but when I use the same hocon:
/TableBridgeActor {
dispatcher = akka.actor.synchronized-dispatcher
}
In my xamarin app unfortunately I get the error
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Java.Lang.RuntimeException: Can't create handler inside thread Thread[Thread-12,10,main] that has not called Looper.prepare()
at Java.Interop.JniEnvironment+InstanceMethods.CallObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method,........
If I change the code to
public void HandleTablesResponse(IEnumerable<Table> allTables)
{
Device.BeginInvokeOnMainThread(() =>
{
this.DisplayAlert("Alert", $"{allTables.Count()} total tables", "hmmmmm?");
});
}
It successfully executes. I suspect that the framework might not be correctly resolving the dispatcher thread, perhaps because I am starting the ActorSystem on another thread?!
(Sorry for all the bug reports, I love Akka!!! haha) Let me know if you want me to create another issue.
Hi @Aaronontheweb , I just wanted to quickly followup, while I haven't been able to prove this yet, I think this workaround eventually causes a deadlock in the Xamarin application.
Are you aware of anyone successfully using Akka.NET in a Xamarin project?
Are you aware of anyone successfully using Akka.NET in a Xamarin project?
@MaximG1234 There might be someone in the Gitter channel who has. Try posting your question: http://gitter.im/akkadotnet/akka.net
cc @gshackles - he's used it
I admittedly haven't tried it recently and only really did it in the context of some demo apps, but here's an example of one demo app I've used in the past (a bit of a port of the classic web crawler example): https://github.com/gshackles/akka-samples/tree/master/Mobile/CSharp
This used v1.3.9 (which was current at the time) but did work. I do seem to recall running into issues trying to use remoting/clustering but was able to make use of a local actor system in a Xamarin.Forms app there
I was able to successfully get a cluster forming connected to a Xamarin Android application. This is some example code that someone else might find useful. I havent tried in iOS yet.
https://www.dropbox.com/s/1u80zkdnu2b8yrg/Xamarin-Cluster-Tester.zip
Just wanted to leave this here for anyone who might attempt to do the same thing.
I was experiencing this in a Xamarin.Android app when I updated from Akka.net 1.3.3 to 1.3.4. There was a change in the Ask
implementation that dropped a ConfigureAwait(false)
, and the first call to Ask
is used in setting up the loggers.
I was able to change the following to create the ActorSystem
from:
var actorSystem = ActorSystem.Create("System", config);
to:
var actorSystemTask = Task.Run(() => ActorSystem.Create("System", config)).ConfigureAwait(false);
var actorSystem = actorSystemTask.GetAwaiter().GetResult();
Added https://github.com/akkadotnet/akka.net/pull/4424 as a work-around for this issue.
I am using Akka.Net Version 1.3.16 on .NET Standard 2.0 and have tested with multiple other versions of Akka.NET.
Steps to reproduce problem.
I have checked to ensure:
Akka and Akka.Remote is referenced from both the core and android project.
What else could be wrong here?