Skip to content

Commit 1b96050

Browse files
author
Yennefer
committed
fix: QMCP MaxPower cleanup bounds checking
- Add hasattr() and bounds checking before GPU memory cleanup - Prevents IndexError during KeyboardInterrupt shutdown - Fixes 34+ restart failures
1 parent a0a8c56 commit 1b96050

2 files changed

Lines changed: 64 additions & 17 deletions

File tree

genesis-q-mem/qmcp_cuda_maxpower.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,27 @@ def run(self):
250250

251251
def _cleanup(self):
252252
"""Release GPU memory"""
253-
for i in range(self.num_streams):
254-
del self.states_real[i]
255-
del self.states_imag[i]
256-
del self.hamiltonians[i]
257-
mempool.free_all_blocks()
258-
pinned_mempool.free_all_blocks()
253+
try:
254+
# Check if lists exist and have elements before deleting
255+
if hasattr(self, 'states_real') and self.states_real:
256+
for i in range(min(len(self.states_real), self.num_streams)):
257+
if i < len(self.states_real):
258+
del self.states_real[i]
259+
260+
if hasattr(self, 'states_imag') and self.states_imag:
261+
for i in range(min(len(self.states_imag), self.num_streams)):
262+
if i < len(self.states_imag):
263+
del self.states_imag[i]
264+
265+
if hasattr(self, 'hamiltonians') and self.hamiltonians:
266+
for i in range(min(len(self.hamiltonians), self.num_streams)):
267+
if i < len(self.hamiltonians):
268+
del self.hamiltonians[i]
269+
270+
mempool.free_all_blocks()
271+
pinned_mempool.free_all_blocks()
272+
except Exception as e:
273+
print(f"⚠️ Cleanup warning: {e}")
259274

260275

261276
def main():

genesis-q-mem/qmem_bubble_gateway_v2.py

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python3
22
"""
3-
Q-Mem Bubble.io Gateway - Groq JTV Edition
3+
Q-Mem Bubble.io Gateway - Groq JTV Edition (Middleware Fix)
44
==========================================
55
Secure HTTP gateway with benchmark endpoints:
66
- /api/bench/live - Live metrics JSON
@@ -19,7 +19,7 @@
1919
from fastapi import FastAPI, HTTPException, Security, status, Depends, Response
2020
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
2121
from fastapi.middleware.cors import CORSMiddleware
22-
from fastapi.responses import StreamingResponse, JSONResponse
22+
from fastapi.responses import StreamingResponse, JSONResponse, FileResponse, HTMLResponse
2323
from pydantic import BaseModel
2424
from typing import Optional, Dict, List
2525
import numpy as np
@@ -114,18 +114,13 @@ class PredictResponse(BaseModel):
114114
version="2.0.0-groq-jtv"
115115
)
116116

117-
# CORS middleware
118-
app.add_middleware(
119-
CORSMiddleware,
120-
allow_origins=["*"], # Configure appropriately for production
121-
allow_credentials=True,
122-
allow_methods=["*"],
123-
allow_headers=["*"],
124-
)
125-
126117
# Startup time
127118
GATEWAY_START_TIME = datetime.now()
128119

120+
# NOTE: CORS middleware disabled due to FastAPI 0.101.0 / Starlette 0.52.1 incompatibility
121+
# CORS headers added manually to responses where needed
122+
123+
129124

130125
def verify_token(credentials: HTTPAuthorizationCredentials = Security(security)):
131126
"""Verify bearer token"""
@@ -522,6 +517,43 @@ async def recall_memory(
522517
)
523518

524519

520+
@app.get("/benchmark.html", tags=["static"])
521+
@app.head("/benchmark.html", tags=["static"])
522+
async def serve_benchmark():
523+
"""Serve benchmark.html page"""
524+
html_path = os.path.join(os.path.dirname(__file__), "benchmark.html")
525+
if os.path.exists(html_path):
526+
return FileResponse(html_path, media_type="text/html")
527+
raise HTTPException(status_code=404, detail="benchmark.html not found")
528+
529+
530+
@app.get("/telemetry_results.json", tags=["static"])
531+
@app.head("/telemetry_results.json", tags=["static"])
532+
async def serve_telemetry():
533+
"""Serve telemetry analysis results"""
534+
json_path = os.path.join(os.path.dirname(__file__), "telemetry_results.json")
535+
if os.path.exists(json_path):
536+
return FileResponse(json_path, media_type="application/json")
537+
raise HTTPException(status_code=404, detail="telemetry_results.json not found")
538+
539+
540+
@app.get("/", tags=["static"])
541+
@app.head("/", tags=["static"])
542+
async def serve_root():
543+
"""Redirect root to benchmark page"""
544+
html_path = os.path.join(os.path.dirname(__file__), "benchmark.html")
545+
if os.path.exists(html_path):
546+
return FileResponse(html_path, media_type="text/html")
547+
return JSONResponse(
548+
status_code=200,
549+
content={
550+
"status": "online",
551+
"message": "Q-Mem Gateway",
552+
"endpoints": ["/api/bench/live", "/api/health", "/benchmark.html"]
553+
}
554+
)
555+
556+
525557
def main():
526558
parser = argparse.ArgumentParser(description='Q-Mem Bubble.io Gateway')
527559
parser.add_argument('--host', default='0.0.0.0', help='Bind host')

0 commit comments

Comments
 (0)