Skip to content

Commit 8ddb358

Browse files
committed
fix: thread lock session save updates to prevent dictionary mutation errors
1 parent 7a8507e commit 8ddb358

1 file changed

Lines changed: 28 additions & 19 deletions

File tree

ghostcoder/session.py

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import hashlib
55
import pathlib
6+
import threading
67
from typing import Dict, List, Any, Optional
78

89
class SessionState:
@@ -21,6 +22,7 @@ def __init__(self, project_path: str):
2122
self.git_status: str = ""
2223
self.active_agents: List[str] = []
2324
self.current_task: str = "Idle"
25+
self._lock = threading.Lock()
2426

2527
self._ensure_session_dir()
2628
self.load_git_context()
@@ -98,22 +100,29 @@ def set_current_task(self, task: str):
98100

99101
def save(self):
100102
"""Serialize session data to JSON."""
101-
session_file = os.path.join(self.sessions_dir, f"{self.timestamp}.json")
102-
data = {
103-
"project_path": self.project_path,
104-
"project_hash": self.project_hash,
105-
"timestamp": self.timestamp,
106-
"commands": self.commands,
107-
"errors": self.errors,
108-
"open_files": self.open_files,
109-
"git_branch": self.git_branch,
110-
"git_last_commit": self.git_last_commit,
111-
"git_status": self.git_status,
112-
"active_agents": self.active_agents,
113-
"current_task": self.current_task
114-
}
115-
try:
116-
with open(session_file, "w", encoding="utf-8") as f:
117-
json.dump(data, f, indent=2)
118-
except Exception as e:
119-
print(f"Error saving session state: {e}")
103+
with self._lock:
104+
session_file = os.path.join(self.sessions_dir, f"{self.timestamp}.json")
105+
# Copy mutable lists/dicts to prevent race changes during dumps iteration
106+
commands_copy = list(self.commands)
107+
errors_copy = list(self.errors)
108+
open_files_copy = dict(self.open_files)
109+
active_agents_copy = list(self.active_agents)
110+
111+
data = {
112+
"project_path": self.project_path,
113+
"project_hash": self.project_hash,
114+
"timestamp": self.timestamp,
115+
"commands": commands_copy,
116+
"errors": errors_copy,
117+
"open_files": open_files_copy,
118+
"git_branch": self.git_branch,
119+
"git_last_commit": self.git_last_commit,
120+
"git_status": self.git_status,
121+
"active_agents": active_agents_copy,
122+
"current_task": self.current_task
123+
}
124+
try:
125+
with open(session_file, "w", encoding="utf-8") as f:
126+
json.dump(data, f, indent=2)
127+
except Exception as e:
128+
print(f"Error saving session state: {e}")

0 commit comments

Comments
 (0)