Skip to content

Commit 118b9e5

Browse files
authored
Release mutex when facing AbandonedMutexException (PowerShell#2867)
1 parent 82e35b8 commit 118b9e5

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

PSReadLine/History.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,24 @@ private bool WithHistoryFileMutexDo(int timeout, Action action)
313313
_historyFileMutex.ReleaseMutex();
314314
}
315315
}
316+
317+
// Consider it a failure if we timed out on the mutex.
318+
return false;
316319
}
317320
catch (AbandonedMutexException)
318321
{
319322
retryCount += 1;
323+
324+
// We acquired the mutex object that was abandoned by another powershell process.
325+
// Now, since we own it, we must release it before retry, otherwise, we will miss
326+
// a release and keep holding the mutex, in which case the 'WaitOne' calls from
327+
// all other powershell processes will time out.
328+
_historyFileMutex.ReleaseMutex();
320329
}
321330
} while (retryCount > 0 && retryCount < 3);
322331

323-
// No errors to report, so consider it a success even if we timed out on the mutex.
324-
return true;
332+
// If we reach here, that means we've done the retries but always got the 'AbandonedMutexException'.
333+
return false;
325334
}
326335

327336
private void WriteHistoryRange(int start, int end, bool overwritten)
@@ -427,18 +436,16 @@ private bool MaybeReadHistoryFile()
427436

428437
private void ReadHistoryFile()
429438
{
430-
WithHistoryFileMutexDo(1000, () =>
439+
if (File.Exists(Options.HistorySavePath))
431440
{
432-
if (!File.Exists(Options.HistorySavePath))
441+
WithHistoryFileMutexDo(1000, () =>
433442
{
434-
return;
435-
}
436-
437-
var historyLines = File.ReadAllLines(Options.HistorySavePath);
438-
UpdateHistoryFromFile(historyLines, fromDifferentSession: false, fromInitialRead: true);
439-
var fileInfo = new FileInfo(Options.HistorySavePath);
440-
_historyFileLastSavedSize = fileInfo.Length;
441-
});
443+
var historyLines = File.ReadAllLines(Options.HistorySavePath);
444+
UpdateHistoryFromFile(historyLines, fromDifferentSession: false, fromInitialRead: true);
445+
var fileInfo = new FileInfo(Options.HistorySavePath);
446+
_historyFileLastSavedSize = fileInfo.Length;
447+
});
448+
}
442449
}
443450

444451
void UpdateHistoryFromFile(IEnumerable<string> historyLines, bool fromDifferentSession, bool fromInitialRead)

0 commit comments

Comments
 (0)