I have a long running video task in a Xamarin.Android app; it decodes a video file using a MediaPlayer into a custom OpenGL ES Surface then queues another Surface, encodes the data using a MediaCodec and drains into a ByteBuffer, which then is passed into a MediaMuxer based upon encoder output ByteBuffer availability. The operation works well and fast, until the video file written byte total is over ~1.3GB, at which point the video (but not audio) will lockup.
The app seems to have too many GREFs, as I'm watching them go up and down in realtime, until they're finally well above 46000 GREFs. It seems like the operating system (or app?) is having trouble dumping all of the GREFs via GC, which causes the app to get stuck in the middle of video processing. I'm monitoring the android resources and the total available memory never changes very much at the OS level; the cpu also seems to always have plenty of idle headroom (~28%).
I am outputting to the system console and watching the gref output logging using:
adb shell setprop debug.mono.log gref
The garbage collection seems to not be able to keep up after about 14 minutes. The GREF count goes up, then down, up, then down; eventually, it goes so high that the GREF count stays above 46k, with the following message looping:
09-26 15:07:11.613 I/monodroid-gc(11213): 46111 outstanding GREFs. Performing a full GC!
09-26 15:07:11.898 I/zygote64(11213): Explicit concurrent copying GC freed 9(32KB) AllocSpace objects, 0(0B) LOS objects, 70% free, 2MB/8MB, paused 434us total 63.282ms
09-26 15:07:13.470 D/Mono (11213): GC_TAR_BRIDGE bridges 22974 objects 23013 opaque 1 colors 22974 colors-bridged 22974 colors-visible 22974 xref 1 cache-hit 0 cache-semihit 0 cache-miss 0 setup 3.40ms tarjan 25.53ms scc-setup 14.85ms gather-xref 1.76ms xref-setup 0.50ms cleanup 13.81ms
09-26 15:07:13.470 D/Mono (11213): GC_BRIDGE: Complete, was running for 1798.94ms
09-26 15:07:13.470 D/Mono (11213): GC_MAJOR: (user request) time 54.95ms, stw 57.82ms los size: 5120K in use: 1354K
09-26 15:07:13.470 D/Mono (11213): GC_MAJOR_SWEEP: major size: 7648K in use: 6120K
and the GREF logs look like this... except multiplied by tens of thousands. And I can watch this number go up, then down, up then down, up then down, until the numbers are massive and eventually so far above 46k that it seems like the app (or OS?) gives up trying to clear these GREFs
grefc 38182 gwrefc 5 38182 is the number that goes massively up then down until well over 46k
09-30 22:42:11.013 I/monodroid-gref(20765): -g- grefc 38182 gwrefc 51 handle 0x98156/G from thread 'finalizer'(25420)
09-30 22:42:11.013 I/monodroid-gref(20765): +w+ grefc 38181 gwrefc 52 obj-handle 0x980f6/G -> new-handle 0xbc3/W from thread 'finalizer'(25420)
09-30 22:42:11.013 I/monodroid-gref(20765): -g- grefc 38181 gwrefc 52 handle 0x980f6/G from thread 'finalizer'(25420)
and there's also these warnings from the GC system warning: not replacing previous registered handle 0x30192 with handle 0x62426 for key_handle 0x9b1ac32
10-03 13:15:25.453 I/monodroid-gref(22127): +g+ grefc 24438 gwrefc 0 obj-handle 0x9/I -> new-handle 0x62416/G from thread 'Thread Pool Worker'(44)
10-03 13:15:25.476 I/monodroid-gref(22127): +g+ grefc 24439 gwrefc 0 obj-handle 0x30192/I -> new-handle 0x62426/G from thread 'Thread Pool Worker'(44)
10-03 13:15:25.477 I/monodroid-gref(22127): warning: not replacing previous registered handle 0x30192 with handle 0x62426 for key_handle 0x9b1ac32
10-03 13:15:25.483 I/monodroid-gref(22127): +g+ grefc 24440 gwrefc 0 obj-handle 0x9/I -> new-handle 0x62436/G from thread 'Thread Pool Worker'(44)
Additionally, it seems like the video freezes while the garbage collection is running, even when that happens without getting stuck in a loop. This is another problem I'm looking for tips or answers on.
This code was ported from another project; I noticed that the previous developer mentioned
// Even if we don't access the SurfaceTexture after the constructor returns, we
// still need to keep a reference to it. The Surface doesn't retain a reference
// at the Java level, so if we don't either then the object can get GCed, which
// causes the native finalizer to run.
I'm thinking this is the key to the problem that I'm experiencing, but what I'm confused about is how the app is supposed to continue encoding if the garbage collection can't run. I see a ton of these in the GREF logs:
10-03 13:07:04.897 I/monodroid-gref(22127): +g+ grefc 6472 gwrefc 4825 obj-handle 0x3727/W -> new-handle 0x2982a/G from thread 'finalizer'(24109)
So is this GREF log entry an indication that I need the finalizer to finish? Or is it an indication that I should have never allowed the finalizer to run before the video is finished encoding?
I did some reading about this and checked out java code doing the same type of operation. At that point I tried adding in a WeakReference to the parent class. The video encoding seems to get a lot further along with the weak reference, but it still eventually locks up.
private void setup() {
_textureRender = new TextureRender();
_textureRender.SurfaceCreated();
// Even if we don't access the SurfaceTexture after the constructor returns, we
// still need to keep a reference to it. The Surface doesn't retain a reference
// at the Java level, so if we don't either then the object can get GCed, which
// causes the native finalizer to run.
_surfaceTexture = new SurfaceTexture(_textureRender.TextureId);
Parent.WeakSurfaceTexture.FrameAvailable += FrameAvailable; // notice the Weak references here
_surface = new Surface(Parent.WeakSurfaceTexture);
}
Here's how I'm getting the weak parent reference:
public System.WeakReference weakParent;
private OutputSurface Parent {
get {
if (weakParent == null || !weakParent.IsAlive)
return null;
return weakParent.Target as OutputSurface;
}
}
public SurfaceTexture WeakSurfaceTexture {
get { return Parent.SurfaceTexture; }
}
When the app is actually locked in a GC loop, it's stuck on this
var curDisplay = EGLContext.EGL.JavaCast<IEGL10>().EglGetCurrentDisplay();
in this context:
const int TIMEOUT_MS = 20000;
public bool AwaitNewImage(bool returnOnFailure = false) {
System.Threading.Monitor.Enter (_frameSyncObject);
while (!IsFrameAvailable) {
try {
// Wait for onFrameAvailable() to signal us. Use a timeout to avoid
// stalling the test if it doesn't arrive.
System.Threading.Monitor.Wait (_frameSyncObject, TIMEOUT_MS);
if (!IsFrameAvailable) {
if (returnOnFailure) {
return false;
}
// TODO: if "spurious wakeup", continue while loop
//throw new RuntimeException ("frame wait timed out");
}
} catch (InterruptedException ie) {
if (returnOnFailure) {
return false;
}
// shouldn't happen
//throw new RuntimeException (ie);
} catch (Exception ex) { throw ex; }
}
IsFrameAvailable = false;
System.Threading.Monitor.Exit (_frameSyncObject);
//the app is locking up on the next line:
var curDisplay = EGLContext.EGL.JavaCast<IEGL10>().EglGetCurrentDisplay();
_textureRender.CheckGlError ("before updateTexImage");
Parent.WeakSurfaceTexture.UpdateTexImage ();
return true;
}
So is this an issue where I need to prevent the finalizer from running? Or is it an issue where the finalizer is causing too many GREFs? Do I need to dispose of some of these frame render SurfaceTextures before I continue processing the video? Do I need to pause the MediaPlayer and dump all of these references before I continue the read/write process?
Do I need to just optimize my code somehow? I read that if there's too many Java.Lang.Object instantiations or usages that it can cause a GREF overflow (or something like that?). I combed through my code and couldn't find anything inheriting from Java.Lang.Object that is getting run in this loop.
Or am I way off and it's something else?
I am basically just trying to figure out how to resolve a video encoder lockup during a GC loop. Any pointers or things to look for would be much appreciated. I've also noticed that the garbage collection (when it's happening) seems to be causing the frame to stutter briefly, so that's something I'm trying to resolve aswell.
Here's the full code base:
https://github.com/hexag0d/BitChute_Mobile_Android_BottomNav/blob/VideoPreProcessing_/PtOffsetRedux/VideoEncoding/OutputSurface.cs
Please advise
EDIT: I just noticed that the branch I posted had inherited from Java.Lang.Object on the OutputSurface class. I removed this and pushed the branch again. I have a bunch of branches trying to get this working and I had backtracked to a branch that still inherited from this class. I know that in many previous attempts I had removed all Java.Lang.Object inheritances from the project and it was still locking up on the GC.
UPDATE: When I run the code in the branch above, I don't see the GREFs going over 46k, but the video seems to still be locking up on the garbage collection; it's just that now the video processing will actually finish, and the GREF count is still getting really close to 46k. I think with a really long video it'd still get tipped over 46k, as the count continually goes up while the processing gets further through the video.
It turns out that all I had to do was comment out the line I had mentioned as being suspect:
var curDisplay = EGLContext.EGL.JavaCast<IEGL10>().EglGetCurrentDisplay();
It runs in a loop that gets called thousands of times for a complete video to finish.
What must have been happening is that these EGLDisplay instances (var) were not being properly garbage collected. I would have thought they'd get automatically collected when the method is finished, but something was stopping that from happening. If you know more about this feel free to give a better answer; I'm not exactly sure what caused the finalizer to get hung up on those objects.
That alone won't really do anyone very much in solving this type of problem, so here's how I figured it out:
first I added this code to the MainActivity OnCreate .. this writes the GREF logs to a file in the /download folder at the root of the droid device then loops and updates every 120 seconds (or whatever interval you choose)
#if DEBUG
Task.Run(async () =>
{
const int seconds = 120;
const string grefTag = "monodroid-gref";
const string grefsFile = "grefs.txt";
while (true)
{
var appDir = Application.ApplicationInfo.DataDir;
var grefFile = System.IO.Path.Combine("/data/data", PackageName, "files/.__override__", grefsFile);
var grefFilePublic = System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory + Java.IO.File.Separator + "download", grefsFile);
if (System.IO.File.Exists(grefFile))
{
System.IO.File.Copy(grefFile, grefFilePublic, true);
System.Console.Write(grefTag, $"adb pull {grefFilePublic} {grefsFile}");
}
else
System.Console.Write(grefTag, "no grefs.txt found, gref logging enabled? (adb shell setprop debug.mono.log gref)");
await Task.Delay(seconds * 1000);
}
});
#endif
Then run this command which enables the gref logging on the device
adb shell setprop debug.mono.log gref
Then I ran the app and let the video processor go and eventually bog down. After this, I collected the .txt file from the download folder and inspected using Visual Studio Code (because it handles large files easily)
In my case, there was a loop running over and over that looked like this, repeated thousands of times:
take_weak_global_ref_jni
-g- grefc 25196 gwrefc 7 handle 0x6495a/G from thread 'finalizer'(27691)
take_weak_global_ref_jni
*take_weak obj=0x7c1046df60; handle=0x64106
+w+ grefc 25195 gwrefc 8 obj-handle 0x64106/G -> new-handle 0x953/W from thread 'finalizer'(27691)
take_weak_global_ref_jni
-g- grefc 25195 gwrefc 8 handle 0x64106/G from thread 'finalizer'(27691)
take_weak_global_ref_jni
*take_weak obj=0x7c19c4e630; handle=0x64fd6
+w+ grefc 25194 gwrefc 9 obj-handle 0x64fd6/G -> new-handle 0x963/W from thread 'finalizer'(27691)
take_weak_global_ref_jni
-g- grefc 25194 gwrefc 9 handle 0x64fd6/G from thread 'finalizer'(27691)
take_weak_global_ref_jni
*take_weak obj=0x7c1046df98; handle=0x63d9a
+w+ grefc 25193 gwrefc 10 obj-handle 0x63d9a/G -> new-handle 0x973/W from thread 'finalizer'(27691)
take_weak_global_ref_jni
-g- grefc 25193 gwrefc 10 handle 0x63d9a/G from thread 'finalizer'(27691)
take_weak_global_ref_jni
I think these are the memory addresses that are stuck unable to be collected. Notice the handle=0x64fd6
So I did a search for that address in the .txt file and it led me to this:
+g+ grefc 25190 gwrefc 0 obj-handle 0x4eaba/I -> new-handle 0x64fd6/G from thread 'Thread Pool Worker'(8)
at Android.Runtime.AndroidObjectReferenceManager.CreateGlobalReference (Java.Interop.JniObjectReference value) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Interop.JniObjectReference.NewGlobalRef () [0x00000] in <286213b9e14c442ba8d8d94cc9dbec8e>:0
at Android.Runtime.JNIEnv.NewGlobalRef (System.IntPtr jobject) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Lang.Object.RegisterInstance (Android.Runtime.IJavaObject instance, System.IntPtr value, Android.Runtime.JniHandleOwnership transfer, System.IntPtr& handle) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Lang.Object.SetHandle (System.IntPtr value, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Lang.Object..ctor (System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Javax.Microedition.Khronos.Egl.IEGL10Invoker..ctor (System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at System.Reflection.MonoCMethod.InternalInvoke (System.Reflection.MonoCMethod , System.Object , System.Object[] , System.Exception& ) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Reflection.MonoCMethod.DoInvoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Reflection.MonoCMethod.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at Java.Interop.TypeManager.CreateProxy (System.Type type, System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Interop.TypeManager.CreateInstance (System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer, System.Type targetType) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Lang.Object.GetObject (System.IntPtr handle, Android.Runtime.JniHandleOwnership transfer, System.Type type) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Interop.JavaObjectExtensions._JavaCast[TResult] (Android.Runtime.IJavaObject instance) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Java.Interop.JavaObjectExtensions.JavaCast[TResult] (Android.Runtime.IJavaObject instance) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at Android.Runtime.Extensions.JavaCast[TResult] (Android.Runtime.IJavaObject instance) [0x00000] in <016ee5efc3d0460baf9a60f95885ebbb>:0
at MediaCodecHelper.OutputSurface.AwaitNewImage (System.Boolean returnOnFailure) [0x00079] in C:\repos\BitChute_Mobile_Android_BottomNav_newAppBak - Copy - Copy\VideoEncoding\OutputSurface.cs:298
at MediaCodecHelper.FileToMp4.EncodeFileToMp4 (System.String inputPath, System.String outputPath, System.Boolean encodeAudio, Android.Net.Uri inputUri) [0x00202] in C:\repos\BitChute_Mobile_Android_BottomNav_newAppBak - Copy - Copy\VideoEncoding\FileToMp4.cs:253
at MediaCodecHelper.FileToMp4.Start (Android.Net.Uri inputUri, System.String outputPath, System.String inputPath) [0x00007] in C:\repos\BitChute_Mobile_Android_BottomNav_newAppBak - Copy - Copy\VideoEncoding\FileToMp4.cs:181
at BitChute.Fragments.SettingsFrag+<>c.<StartEncoderTest>b__18_0 () [0x000fe] in C:\repos\BitChute_Mobile_Android_BottomNav_newAppBak - Copy - Copy\Fragments\SettingsFrag.cs:310
at System.Threading.Tasks.Task.InnerInvoke () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.Execute () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.ExecutionContextCallback (System.Object obj) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.ExecuteWithThreadLocal (System.Threading.Tasks.Task& currentTaskSlot) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.ExecuteEntry (System.Boolean bPreventDoubleExecution) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
handle 0x64fd6; key_handle 0x259aa25: Java Type: `com/google/android/gles_jni/EGLImpl`; MCW type: `Javax.Microedition.Khronos.Egl.IEGL10Invoker`
notice Javax.Microedition.Khronos.Egl.IEGL10Invoker and handle 0x64fd6
I recommend checking the memory handles in the part where your GC is getting stuck in a loop; then search for those handles and see if you can find the type that they are referencing. After you've found what type the loop is stuck trying to GC, you will need to back track through the source code and find a spot where this type is being called (or instantiated) in a loop. I think it's typically (from what I've read) loops that are generating undisposed Java.Lang.Object references which cause the GC to fail.
So I knew at that point it was something related to the interface IEGL10. I went back and tried just removing from the loop and it worked! GREFs never go above 600 now.
quick steps:
1. enable gref logging
2. run app
3. check logs for the memory addresses that are not being collected properly (where your app gets stuck in a GC loop, you'll likely see
a ton of repeated lines)
4. search for those memory addresses
5. check for the object **type** that is in the memory handle assignment stack trace
6. go back to your long running problematic loops and see if you can find a matching method being called or an object instantiation in rapid succession and not
being disposed of
7. either `Dispose` your looped objects manually or I also read to try and avoid `Java.Lang.Object` inheritance if it's in a long
running loop.
You likely won't be as lucky as me where I can just comment out a line of code. You'll probably have to figure out a way to dispose of the looped object manually or do something else to notify the app it can safely GC those objects, but the memory addresses should give you a clue as to which object is causing a problem with the GC.
I'm sorry if that isn't the greatest answer, but I'm not very familiar with how GC works. If anyone can give a better explanation I would be curious to hear more details on this, but that's how I fixed mine! Hope it helps
I'm currently have a project where I try to get information from the NZBIndex.nl API using a C# console-application.
My request looks like this:
using (WebClient c = new WebClient())
{
var response = c.DownloadString("https://nzbindex.com/search/json?sort=agedesc&hidespam=1&q=Ubuntu");
Console.WriteLine(response);
//...
}
This worked fine in my main function and when executing it in a manually created thread. But it throws errors when running the code snipped in a function that gets called by a ThreadPool like this:
ThreadPool.QueueUserWorkItem(CheckMethod, item);
The errors that get thrown when running it with ThreadPool look like this:
Thread was being aborted.
at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_threads_state_poll()
at System.Uri.GetComponentsHelper (System.UriComponents uriComponents, System.UriFormat uriFormat) <0x40a23510 + 0x00033> in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Uri.GetComponents (System.UriComponents components, System.UriFormat format) [0x00072] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Uri.GetParts (System.UriComponents uriParts, System.UriFormat formatAs) [0x00000] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Uri.get_Query () [0x00041] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Net.WebClient.GetUri (System.Uri address) [0x00035] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Net.WebClient.GetUri (System.String address) [0x0004c] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at System.Net.WebClient.DownloadString (System.String address) [0x00000] in <4e15bbae9d7043d8afd6cfd50bd9bd5a>:0
at (wrapper remoting-invoke-with-check) System.Net.WebClient.DownloadString(string)
at DBErrorcheck.Program.CheckThread (System.Object o) [0x00039] in <cf4c719a35df4ff094732dd5a9e883e9>:0
Debugging it doesn't really help since the programm stops after executing the DownloadString
I just found the answer for this issue while trying to make a minimal reproducable example.
This error seems to be caused when a thread in the ThreadPool is still running but the main already exits. I found this out because with a Thread.Sleep(500) it fixed for me.
I guess a better way would be to check if the Pools has any jobs left.
I'm making an Android app (using Unity and C#) which needs to connect over TCP to a different app running on another device (using the .NET System.Net.Sockets.TcpClient and TcpListener classes). The way this works is the host app broadcasts a UDP packet giving info on its local IP (192.168.x.x) and its TCP listening port. Upon receiving the UDP packet, the Android app attempts to connect to the TCP endpoint given. Most of the time (~80%), this works perfectly and the two devices establish a valid TCP connection. Sometimes though, the Android app receives the UDP packet, tries to connect over TCP but a "No Route To Host" socket error shows up instead; even trying again upon receiving the next UDP packet fails.
I'm suspecting that this is to do with the router creating different subnets. I'm not very familiar with networking code, so I'm not sure how to forward the TCP request over to a different subnet of the local network. What's weird is that the UDP packet is always received no matter what; and most of the time, the TCP request will fail for 10 minutes straight then start working again like nothing happened.
public async Task<bool> ConnectToHost(IPEndPoint endpoint) {
try {
TcpClient client = new TcpClient();
client.NoDelay = true;
IPAddress ipv4 = endpoint.Address;
Debug.Log("IPv4: " + ipv4);
await client.ConnectAsync(ipv4, endpoint.Port); // <--- this call throws the SocketException
Debug.Log("Connected.");
// ...
return true;
}catch(SocketException se) {
Debug.LogError("[TCPClient] Socket Exception (" + se.ErrorCode + "), cannot connect to host: " + se.ToString(), this);
}catch(Exception e) {
Debug.LogError("[TCPClient] Error, cannot connect to host: " + e.ToString(), this);
}
return false;//Could not connect
}
The ConnectAsync() call fails on the client side, giving the following SocketException (error code 10065, WSAEHOSTUNREACH); on server side, no trace of the message is ever seen.
05-29 13:31:54.591: I/Unity(24587): IPv4: 192.168.1.21
05-29 13:31:54.591: I/Unity(24587):
05-29 13:31:54.591: I/Unity(24587): (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 48)
05-29 13:31:58.103: E/Unity(24587): [TCPClient] Socket Exception (10065), cannot connect to host: System.Net.Sockets.SocketException (0x80004005): No route to host
05-29 13:31:58.103: E/Unity(24587): at System.Net.Sockets.SocketAsyncResult.CheckIfThrowDelayedException () [0x00014] in <9eab73f5583e4ab3921ff80e74ccdb29>:0
05-29 13:31:58.103: E/Unity(24587): at System.Net.Sockets.Socket.EndConnect (System.IAsyncResult asyncResult) [0x0002c] in <9eab73f5583e4ab3921ff80e74ccdb29>:0
05-29 13:31:58.103: E/Unity(24587): at System.Net.Sockets.TcpClient.EndConnect (System.IAsyncResult asyncResult) [0x0000c] in <9eab73f5583e4ab3921ff80e74ccdb29>:0
05-29 13:31:58.103: E/Unity(24587): at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncCoreLogic (System.IAsyncResult iar, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Threading.Tasks.Task`1[TResult] promise, System.Boolean requiresSynchronization) [0x00019] in <a6266edc72ee4a578659208aefcdd5e1>:0
Configuration on a single machine:
I have single server node
<ignite xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection" gridName="myGrid1">
<clientConnectorConfiguration port="10800"/>
<discoverySpi type="TcpDiscoverySpi" localPort='48500' localPortRange='1'>
<ipFinder type="TcpDiscoveryStaticIpFinder">
<endpoints>
<string>127.0.0.1:48500</string>
</endpoints>
</ipFinder>
</discoverySpi>
<communicationSpi type='TcpCommunicationSpi' localPort='48100' />
And thin client node:
Ignition.StartClient(new IgniteClientConfiguration { Host = "127.0.0.1", Port = 10800})
So I'm trying to make a next test:
1) shutdown server node
2) start server node againg
3) check connection from client node to server node
The problem is after 2 step when I call method
ignite.GetCache<long,Entity>("cacheName").TryGet(id, out item)
I get an exception
System.IO.IOException: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.
---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace --- at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size
at Apache.Ignite.Core.Impl.Client.ClientSocket.SendRequest(RequestMessage& reqMsg) at Apache.Ignite.Core.Impl.Client.ClientSocket.DoOutInOp[T](ClientOp opId, Action1 writeAction, Func2 readFunc, Func3 errorFunc) at Apache.Ignite.Core.Impl.Client.Cache.CacheClient2.DoOutInOp[T](ClientOp opId, Action1 writeAction, Func2 readFunc
at Apache.Ignite.Core.Impl.Client.Cache.CacheClient`2.TryGet(TK key, TV& value)
I am afraid that automatic reconnect is not supported by .Net thin client.
From the source code, Client is created once right away, which does Handshake once right away. There's no reconnect code in sight. There is an issue filed about Failover feature in Apache Ignite JIRA: not just reconnect, but try different node addresses.
This means you will have to check for disconnects and reconnect manually.
I am using web references in my app but I am getting following exception.
I have used bellow code.
obj is my web reference object. It does not take obj directly that is why I have used variable for that. But still it's not working, it takes me automatically to previous activity.
var url=obj.ToString();
// Create a new WebRequest Object to the mentioned URL.
WebRequest myWebRequest=WebRequest.Create(url);
Console.WriteLine("\nThe Timeout time of the request before setting is : {0} milliseconds",myWebRequest.Timeout);
// Set the 'Timeout' property in Milliseconds.
myWebRequest.Timeout=10000;
// This request will throw a WebException if it reaches the timeout limit before it is able to fetch the resource.
WebResponse myWebResponse=myWebRequest.GetResponse();
Unhandled Exception: System.Net.WebException: The request timed out
at System.Net.HttpWebRequest.EndGetResponse (IAsyncResult asyncResult)
[0x00000] in :0 at
System.Net.HttpWebRequest.GetResponse () [0x00000] in :0 at
System.Web.Services.Protocols.WebClientProtocol.GetWebResponse
(System.Net.WebRequest request) [0x00000] in :0
It hit your timeout, meaning it did not get a response from the URL it called in time.
Check the URL in a browser. Check if it returns anything and how long it takes.
Make sure you don't need to configure a proxy.