Skip to content

Commit 3710389

Browse files
committed
fix: server not exit after idle
1 parent ac69219 commit 3710389

1 file changed

Lines changed: 66 additions & 25 deletions

File tree

src/embeddings/http_embedding.py

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def get_server_info_path() -> Path:
3535
return cache_dir / "embedding_server.json"
3636

3737

38+
def get_server_log_path() -> Path:
39+
"""Get the path to the server log file."""
40+
from ..config.config import Config
41+
config = Config()
42+
cache_dir = Path(config.get_database_path())
43+
return cache_dir / "embedding_server.log"
44+
45+
3846
class HttpEmbedding(EmbeddingInterface):
3947
"""HTTP client that connects to the shared embedding server."""
4048

@@ -86,28 +94,50 @@ def _spawn_server(self):
8694
# Use the same Python interpreter
8795
python_exe = sys.executable
8896

89-
# Create a detached subprocess that survives parent exit
90-
if os.name == 'nt': # Windows
91-
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS
92-
self._server_process = subprocess.Popen(
93-
[python_exe, "-m", "src.embedding_server", "--port", str(self.port)],
94-
creationflags=creationflags,
95-
stdout=subprocess.DEVNULL,
96-
stderr=subprocess.DEVNULL,
97-
cwd=str(Path(__file__).parent.parent.parent),
98-
)
99-
else: # Unix
100-
# Use nohup-style detachment
101-
self._server_process = subprocess.Popen(
102-
[python_exe, "-m", "src.embedding_server", "--port", str(self.port)],
103-
stdout=subprocess.DEVNULL,
104-
stderr=subprocess.PIPE, # Keep stderr for debugging
105-
stdin=subprocess.DEVNULL,
106-
start_new_session=True, # Detach from parent
107-
cwd=str(Path(__file__).parent.parent.parent),
108-
)
97+
# Redirect stderr to a log file to avoid pipe buffer filling up and blocking
98+
log_path = get_server_log_path()
99+
100+
# Rotate log if too large (10MB)
101+
try:
102+
if log_path.exists() and log_path.stat().st_size > 10 * 1024 * 1024:
103+
old_log = log_path.with_suffix(".log.old")
104+
log_path.rename(old_log)
105+
except Exception as e:
106+
print(f"Warning: Failed to rotate log file: {e}", file=sys.stderr)
109107

110-
print(f"Spawned embedding server (PID {self._server_process.pid})", file=sys.stderr)
108+
try:
109+
# Open in append mode
110+
log_file = open(log_path, "a")
111+
except Exception as e:
112+
print(f"Warning: Could not open log file {log_path}: {e}", file=sys.stderr)
113+
log_file = subprocess.DEVNULL
114+
115+
try:
116+
# Create a detached subprocess that survives parent exit
117+
if os.name == 'nt': # Windows
118+
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP | subprocess.DETACHED_PROCESS
119+
self._server_process = subprocess.Popen(
120+
[python_exe, "-m", "src.embedding_server", "--port", str(self.port)],
121+
creationflags=creationflags,
122+
stdout=subprocess.DEVNULL,
123+
stderr=log_file,
124+
cwd=str(Path(__file__).parent.parent.parent),
125+
)
126+
else: # Unix
127+
# Use nohup-style detachment
128+
self._server_process = subprocess.Popen(
129+
[python_exe, "-m", "src.embedding_server", "--port", str(self.port)],
130+
stdout=subprocess.DEVNULL,
131+
stderr=log_file,
132+
stdin=subprocess.DEVNULL,
133+
start_new_session=True, # Detach from parent
134+
cwd=str(Path(__file__).parent.parent.parent),
135+
)
136+
finally:
137+
if log_file != subprocess.DEVNULL:
138+
log_file.close()
139+
140+
print(f"Spawned embedding server (PID {self._server_process.pid}) logging to {log_path}", file=sys.stderr)
111141

112142
def _ensure_server(self):
113143
"""Ensure the embedding server is running, spawning if needed.
@@ -159,10 +189,21 @@ def _ensure_server(self):
159189

160190
# Check if process died
161191
if self._server_process and self._server_process.poll() is not None:
162-
stderr_output = ""
163-
if self._server_process.stderr:
164-
stderr_output = self._server_process.stderr.read().decode('utf-8', errors='replace')
165-
raise RuntimeError(f"Embedding server failed to start. Exit code: {self._server_process.returncode}\nStderr: {stderr_output}")
192+
# Read last few lines of log file for error details
193+
stderr_output = "Check log file for details"
194+
try:
195+
log_path = get_server_log_path()
196+
if log_path.exists():
197+
# Read last 1KB
198+
size = log_path.stat().st_size
199+
with open(log_path, 'r') as f:
200+
if size > 1024:
201+
f.seek(size - 1024)
202+
stderr_output = f.read()
203+
except Exception:
204+
pass
205+
206+
raise RuntimeError(f"Embedding server failed to start. Exit code: {self._server_process.returncode}\nLog tail: {stderr_output}")
166207

167208
raise RuntimeError(f"Embedding server failed to start within {STARTUP_TIMEOUT}s")
168209

0 commit comments

Comments
 (0)