Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Runtime/BacktraceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ private void OnDestroy()
Application.lowMemory -= HandleLowMemory;
_nativeClient?.Disable();
#endif

}

/// <summary>
Expand Down Expand Up @@ -725,6 +724,11 @@ private void CaptureUnityMessages()
}
}

internal void OnApplicationPause(bool pause)
{
_nativeClient?.PauseAnrThread(pause);
}

internal void HandleUnityBackgroundException(string message, string stackTrace, LogType type)
{
// validate if a message is from main thread
Expand Down
82 changes: 56 additions & 26 deletions Runtime/Native/Android/NativeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ namespace Backtrace.Unity.Runtime.Native.Android
internal class NativeClient : INativeClient
{
// Last Backtrace client update time
internal float _lastUpdateTime;
volatile internal float _lastUpdateTime;

/// <summary>
/// Determine if the ANR background thread should be disabled or not
/// for some period of time.
/// This option will be used by the native client implementation
/// once application goes to background/foreground
/// </summary>
volatile internal bool _preventAnr = false;

/// <summary>
/// Determine if ANR thread should exit
/// </summary>
volatile internal bool _stopAnr = false;

private Thread _anrThread;

Expand Down Expand Up @@ -301,42 +314,50 @@ public void HandleAnr(string gameObjectName, string callbackName)
_anrThread = new Thread(() =>
{
float lastUpdatedCache = 0;
while (true)
while (_anrThread.IsAlive && _stopAnr == false)
{
if (lastUpdatedCache == 0)
if (!_preventAnr)
{
lastUpdatedCache = _lastUpdateTime;
}
else if (lastUpdatedCache == _lastUpdateTime)
{
if (!reported)
if (lastUpdatedCache == 0)
{

reported = true;
if (AndroidJNI.AttachCurrentThread() == 0)
lastUpdatedCache = _lastUpdateTime;
}
else if (lastUpdatedCache == _lastUpdateTime)
{
if (!reported)
{
// set temporary attribute to "Hang"
AddAttribute(
AndroidJNI.NewStringUTF("error.type"),
AndroidJNI.NewStringUTF("Hang"));

NativeReport(AndroidJNI.NewStringUTF("ANRException: Blocked thread detected."));
// update error.type attribute in case when crash happen
SetAttribute("error.type", "Crash");

reported = true;
if (AndroidJNI.AttachCurrentThread() == 0)
{
// set temporary attribute to "Hang"
AddAttribute(
AndroidJNI.NewStringUTF("error.type"),
AndroidJNI.NewStringUTF("Hang"));

NativeReport(AndroidJNI.NewStringUTF("ANRException: Blocked thread detected."));
// update error.type attribute in case when crash happen
SetAttribute("error.type", "Crash");
}
}
}
else
{
reported = false;
}

lastUpdatedCache = _lastUpdateTime;
}
else
else if (lastUpdatedCache != 0)
{
reported = false;
// make sure when ANR happened just after going to foreground
// we won't false positive ANR report
lastUpdatedCache = 0;
}

lastUpdatedCache = _lastUpdateTime;
Thread.Sleep(5000);

}
});

_anrThread.IsBackground = true;
_anrThread.Start();
}

Expand Down Expand Up @@ -389,8 +410,17 @@ public void Disable()
{
if (_anrThread != null)
{
_anrThread.Abort();
_stopAnr = true;
}
}

/// <summary>
/// Pause ANR detection
/// </summary>
/// <param name="stopAnr">True - if native client should pause ANR detection"</param>
public void PauseAnrThread(bool stopAnr)
{
_preventAnr = stopAnr;
}
}
}
6 changes: 6 additions & 0 deletions Runtime/Native/INativeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ internal interface INativeClient
/// Disable native integration
/// </summary>
void Disable();

/// <summary>
/// Pause ANR thread
/// </summary>
/// <param name="state">True if should pause, otherwise false.</param>
void PauseAnrThread(bool state);
}
}
72 changes: 52 additions & 20 deletions Runtime/Native/iOS/NativeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,20 @@ namespace Backtrace.Unity.Runtime.Native.iOS
internal class NativeClient : INativeClient
{
// Last Backtrace client update time
internal float _lastUpdateTime;
volatile internal float _lastUpdateTime;

/// <summary>
/// Determine if the ANR background thread should be disabled or not
/// for some period of time.
/// This option will be used by the native client implementation
/// once application goes to background/foreground
/// </summary>
volatile internal bool _preventAnr = false;

/// <summary>
/// Determine if ANR thread should exit
/// </summary>
volatile internal bool _stopAnr = false;

private Thread _anrThread;

Expand Down Expand Up @@ -139,35 +152,45 @@ public void HandleAnr(string gameObjectName, string callbackName)
_anrThread = new Thread(() =>
{
float lastUpdatedCache = 0;
while (true)
while (_anrThread.IsAlive && _stopAnr == false)
{
if (lastUpdatedCache == 0)
if (!_preventAnr)
{
lastUpdatedCache = _lastUpdateTime;
}
else if (lastUpdatedCache == _lastUpdateTime)
{
if (!reported)
if (lastUpdatedCache == 0)
{
// set temporary attribute to "Hang"
SetAttribute("error.type", "Hang");
NativeReport("ANRException: Blocked thread detected.");
// update error.type attribute in case when crash happen
SetAttribute("error.type", "Crash");
reported = true;
lastUpdatedCache = _lastUpdateTime;
}
else if (lastUpdatedCache == _lastUpdateTime)
{
if (!reported)
{
// set temporary attribute to "Hang"
SetAttribute("error.type", "Hang");
NativeReport("ANRException: Blocked thread detected.");
// update error.type attribute in case when crash happen
SetAttribute("error.type", "Crash");
reported = true;
}
}
else
{
reported = false;
}


lastUpdatedCache = _lastUpdateTime;
}
else
else if (lastUpdatedCache != 0)
{
reported = false;
// make sure when ANR happened just after going to foreground
// we won't false positive ANR report
lastUpdatedCache = 0;
}

lastUpdatedCache = _lastUpdateTime;
Thread.Sleep(5000);

}
});

_anrThread.IsBackground = true;
_anrThread.Start();
}

Expand Down Expand Up @@ -228,9 +251,18 @@ public void Disable()
{
if (_anrThread != null)
{
_anrThread.Abort();
_stopAnr = true;
}
}

/// <summary>
/// Pause ANR detection
/// </summary>
/// <param name="stopAnr">True - if native client should pause ANR detection"</param>
public void PauseAnrThread(bool stopAnr)
{
_preventAnr = stopAnr;
}
}
}
#endif