Skip to content

Commit 3e43e52

Browse files
committed
Add timeout on thread join on shutdown and suppress ThreadAbortException
The timeout on the thread join matches the maximum amount of time that should be spent on a PollConnection anyway, before the thread is aborted. ThreadAbortExceptions are now explicity caught and suppressed without logging to avoid erroneous log messages in normal operation.
1 parent e341134 commit 3e43e52

2 files changed

Lines changed: 18 additions & 7 deletions

File tree

Packages/Tracking/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
[docs-website]: https://docs.ultraleap.com/unity-api/ "Ultraleap Docs"
88

9+
## NEXT
10+
11+
### Fixed
12+
- Fixed an issue with ThreadAbortExceptions being raised during normal shutdown.
13+
914
## [7.3.0] - 25/02/2026
1015

1116
### Added

Packages/Tracking/Core/Runtime/Plugins/LeapCSharp/Connection.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ namespace LeapInternal
1717

1818
public class Connection
1919
{
20+
private const uint DEFAULT_TIMEOUT_MILLISECONDS = 150;
21+
2022
public struct Key
2123
{
2224
public readonly int connectionId;
@@ -272,7 +274,9 @@ public void Stop()
272274
//before trying to join the worker thread.
273275
LeapC.CloseConnection(_leapConnection);
274276

275-
_polster.Join();
277+
//Using a timeout for Join() to prevent the application from hanging
278+
//if the worker thread does not exit quickly during shutdown.
279+
_polster.Join((int)DEFAULT_TIMEOUT_MILLISECONDS);
276280
}
277281

278282
/// <summary>
@@ -308,9 +312,7 @@ private void processMessages()
308312
}
309313

310314
LEAP_CONNECTION_MESSAGE _msg = new LEAP_CONNECTION_MESSAGE();
311-
uint timeout = 150;
312-
313-
result = LeapC.PollConnection(_leapConnection, timeout, ref _msg);
315+
result = LeapC.PollConnection(_leapConnection, DEFAULT_TIMEOUT_MILLISECONDS, ref _msg);
314316

315317
if (result != eLeapRS.eLeapRS_Success)
316318
{
@@ -407,6 +409,11 @@ private void processMessages()
407409
}
408410
} //while running
409411
}
412+
catch (ThreadAbortException)
413+
{
414+
// Handle thread abort gracefully without logging as this can occur under normal circumstances.
415+
_isRunning = false;
416+
}
410417
catch (Exception e)
411418
{
412419
Logger.Log("Exception: " + e);
@@ -1031,12 +1038,11 @@ public static bool IsConnectionAvailable(string serverNamespace = "Leap Service"
10311038
}
10321039

10331040
LEAP_CONNECTION_MESSAGE _msg = new LEAP_CONNECTION_MESSAGE();
1034-
uint timeout = 150;
1035-
result = LeapC.PollConnection(tempConnection, timeout, ref _msg);
1041+
LeapC.PollConnection(tempConnection, DEFAULT_TIMEOUT_MILLISECONDS, ref _msg);
10361042

10371043
LEAP_CONNECTION_INFO pInfo = new LEAP_CONNECTION_INFO();
10381044
pInfo.size = (uint)Marshal.SizeOf(pInfo);
1039-
result = LeapC.GetConnectionInfo(tempConnection, ref pInfo);
1045+
LeapC.GetConnectionInfo(tempConnection, ref pInfo);
10401046

10411047
if (pInfo.status == eLeapConnectionStatus.eLeapConnectionStatus_Connected)
10421048
{

0 commit comments

Comments
 (0)