Please sign in to comment.
[WaitHandle] Fix Wait(One|Any|All) and SignalAndWait with timeout
In the case where we would call for example WaitHandle.WaitOne with a timeout, we could run in the case where we would wait way longer than the timeout would allow it (240s instead of 90s for example). This would be due to spurious wake, which would not be considered to be an error, but which would lead calling the `mono_os_cond_timedwait` function with the same timeout every time. That would mean that `mono_os_cond_timedwait` would return that it timedout, if and only if, it would timed out after N milliseconds, with N the millisecondsTimeout parameter to WaitOne in this example. That mean that any spurious wake would effectively lead to rewaiting with a full timeout every time. That could lead to the following scenario: - T1 calls waitHandle.WaitOne(timeout = 1000ms) at T=0ms - T1 calls mono_os_cond_timedwait(timeout = 1000) at T=0ms - GC suspend T1 at T=500ms <- here it's not necessarily the GC, it can be anything suspending/signaling the thread - T1 spurious wake, and call mono_os_cond_timedwait(timeout = 1000) at T=500ms - GC interrupt T1 at T=1250ms - T1 spurious wake, and call mono_os_cond_timedwait(timeout = 1000) at T=1250ms - etc. As you can see, T1 should have returned from waitHandle.WaitOne before the second spurious wake, but as it recalled mono_os_cond_timedwait with a timeout of 1000ms again, it didn't. The fix consists in keeping track of when the call is supposed to finish, and pass an adaptable timeout to mono_os_cond_timedwait, which decreases as time goes on, to enventually reach 0, and return in a timely manner. Fixes https://bugzilla.xamarin.com/show_bug.cgi?id=38382
- Loading branch information...
Showing with 134 additions and 3 deletions.