Skip to content

Race condition in FileLogStorage.Clear() / BufferedFileLogStorage.Clear() causes "file being used by another process" on Console/ClearLogs #855

Description

@KageTrips

Environment

Package: com.ivanmurzak.unity.mcp v0.82.3 (latest, registry source)
Unity: 6000.3.8f1
OS: Windows 11
Reproduces consistently in an actively-running Editor session (game in Play Mode / logging happening), intermittently otherwise
Summary
Calling the Console / Clear Logs MCP tool (console-clear-logs) intermittently fails with:

Tool execution failed for 'Console / Clear Logs': One or more errors occurred.
(The process cannot access the file 'Temp\mcp-server\ai-editor-logs.txt'
because it is being used by another process.)
This happens repeatedly across sessions whenever any Unity log message is emitted around the same time as a Clear Logs call.

Root cause

Console.ClearLogs.cs marshals to the main thread and runs Debug.ClearDeveloperConsole() then logCollector.Clear(). FileLogStorage.Clear() (and the BufferedFileLogStorage override) do:

lock (_fileMutex)
{
fileWriteStream?.Dispose();
fileWriteStream = null;
if (File.Exists(filePath))
File.Delete(filePath); // <-- fails here intermittently
}
UnityLogCollector subscribes to Application.logMessageReceivedThreaded, which Unity invokes synchronously, on the calling thread, for every Debug.Log* call — including calls made by the plugin's own internal logger (UnityLogger → Debug.LogError/LogDebug) as well as any other game/editor code logging at that moment.

If a log message is emitted on the main thread in the window between fileWriteStream = null and File.Delete(filePath), OnLogMessageReceived fires re-entrantly on the same thread (the lock is re-entrant for the owning thread, so this doesn't deadlock — it runs inline) and calls AppendInternal, which does:

fileWriteStream ??= CreateWriteStream(_requestedFileName, out fileName, out filePath);
This re-opens a fresh FileStream (FileShare.ReadWrite, no FileShare.Delete) on the exact file Clear() is about to delete. When the outer Clear() call reaches File.Delete(filePath), that fresh handle is still open, and Windows refuses the delete with IOException (the "another process" wording is generic .NET/Win32 phrasing — here it's actually a second handle from the same process).

Why this is easy to hit

Application.logMessageReceivedThreaded fires for any log line, including ones the plugin itself emits (e.g. FileLogStorage's own _logger.LogDebug("Creating log file stream: {file}", filePath) in CreateWriteStream). In an actively-developed project with a running game loop, some log line landing in that narrow window is close to guaranteed over a long session.

Evidence this is already known

Your own test suite has a documented flake referencing this: PR #848 (ToolThreadSafetyTests) notes "the documented ai-editor-logs.txt TestToolConsole/ConsoleClearLogs file-lock flakes" as a pre-existing environmental issue. This report is meant to give the underlying root cause for that flake.

Suggested fix (roughly most→least surgical)

In Clear(), temporarily unsubscribe (Application.logMessageReceivedThreaded -= OnLogMessageReceived) before disposing/deleting, and re-subscribe after.
Open the FileStream with FileShare.Delete in CreateWriteStream, and tolerate a concurrently-open handle during delete (or rename-then-delete).
Guard AppendInternal against re-entrant re-creation while a Clear()/ResetLogFile() is in progress on the same thread (e.g. an _isClearing flag checked before CreateWriteStream is called from AppendInternal).
Stack trace (example, trimmed)

fail: [03:39:23:5315] [AI] ToolRunnerCollection Tool execution failed for 'Console / Clear Logs': One or more errors occurred. (The process cannot access the file '...\Temp\mcp-server\ai-editor-logs.txt' because it is being used by another process.)
at System.Reflection.RuntimeMethodInfo.Invoke (...)
at com.IvanMurzak.ReflectorNet.MethodWrapper.InvokeDict (...)
at com.IvanMurzak.McpPlugin.RunTool.Run (...)
UnityEngine.Debug:LogError (object)
com.IvanMurzak.Unity.MCP.Utils.UnityLogger:Log<...> (... at ./Library/PackageCache/com.ivanmurzak.unity.mcp@64753ff18699/Runtime/Logger/UnityLogger.cs:119)
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions