Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,33 @@ install-junit-viewer: ## Install junit-viewer for HTML report generation (if not

dev: install-ui install-air setup-workspace $(if $(DEBUG),install-delve) ## Start complete development environment (UI + API with proxy)
@$(EXPOSE_ENV); \
set -m; \
set +m; \
ui_pid=""; \
api_pid=""; \
cleanup() { \
$(ECHO) "$(YELLOW)[make dev] cleanup started; ui_pid=$$ui_pid api_pid=$$api_pid$(NC)"; \
trap - EXIT INT TERM HUP; \
kill %1 %2 2>/dev/null || true; \
for pid in "$$ui_pid" "$$api_pid"; do \
if [ -n "$$pid" ]; then \
children="$$(pgrep -P "$$pid" 2>/dev/null || true)"; \
$(ECHO) "$(YELLOW)[make dev] sending TERM to pid $$pid and children: $${children:-none}$(NC)"; \
kill -TERM $$children "$$pid" 2>/dev/null || true; \
fi; \
done; \
sleep 1; \
kill -KILL %1 %2 2>/dev/null || true; \
for pid in "$$ui_pid" "$$api_pid"; do \
if [ -n "$$pid" ]; then \
children="$$(pgrep -P "$$pid" 2>/dev/null || true)"; \
$(ECHO) "$(YELLOW)[make dev] sending KILL to pid $$pid and remaining children: $${children:-none}$(NC)"; \
kill -KILL $$children "$$pid" 2>/dev/null || true; \
fi; \
done; \
$(ECHO) "$(YELLOW)[make dev] waiting for background jobs to exit...$(NC)"; \
wait 2>/dev/null || true; \
Comment on lines 159 to 178

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Kill the full process tree during make dev cleanup.

This cleanup only targets direct children of the tracked subshell. With the process chain started at Line 225, that can kill the shell and its first child while leaving a deeper long-lived child behind, so the next make dev can come up with a stale process still holding $(PORT).

♻️ Suggested fix
 cleanup() { \
 	$(ECHO) "$(YELLOW)[make dev] cleanup started; ui_pid=$$ui_pid api_pid=$$api_pid$(NC)"; \
 	trap - EXIT INT TERM HUP; \
+	kill_tree() { \
+		local sig="$$1" pid="$$2" child; \
+		for child in $$(pgrep -P "$$pid" 2>/dev/null || true); do \
+			kill_tree "$$sig" "$$child"; \
+		done; \
+		kill -s "$$sig" "$$pid" 2>/dev/null || true; \
+	}; \
 	for pid in "$$ui_pid" "$$api_pid"; do \
 		if [ -n "$$pid" ]; then \
-			children="$$(pgrep -P "$$pid" 2>/dev/null || true)"; \
-			$(ECHO) "$(YELLOW)[make dev] sending TERM to pid $$pid and children: $${children:-none}$(NC)"; \
-			kill -TERM $$children "$$pid" 2>/dev/null || true; \
+			$(ECHO) "$(YELLOW)[make dev] sending TERM to pid $$pid tree$(NC)"; \
+			kill_tree TERM "$$pid"; \
 		fi; \
 	done; \
 	sleep 1; \
 	for pid in "$$ui_pid" "$$api_pid"; do \
 		if [ -n "$$pid" ]; then \
-			children="$$(pgrep -P "$$pid" 2>/dev/null || true)"; \
-			$(ECHO) "$(YELLOW)[make dev] sending KILL to pid $$pid and remaining children: $${children:-none}$(NC)"; \
-			kill -KILL $$children "$$pid" 2>/dev/null || true; \
+			$(ECHO) "$(YELLOW)[make dev] sending KILL to pid $$pid tree$(NC)"; \
+			kill_tree KILL "$$pid"; \
 		fi; \
 	done; \
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 159 - 178, The cleanup() target currently kills only
direct children found via pgrep -P and leaves deeper descendants running; update
it to terminate entire process trees by targeting process groups or recursive
descendants for both ui_pid and api_pid (the variables ui_pid/api_pid and the
cleanup() function are the relevant symbols). Specifically, when sending
TERM/KILL, prefer killing the whole process group (send signals to negative pid
for the process group id) and/or recursively collect all descendant PIDs before
sending signals so no deep child is left running; keep the existing logging
messages and fall back to the pgrep -P approach only if process-group signaling
is unavailable.

$(ECHO) "$(GREEN)[make dev] cleanup completed.$(NC)"; \
}; \
stop_dev() { \
$(ECHO) "$(YELLOW)[make dev] received shutdown signal; starting cleanup...$(NC)"; \
cleanup; \
exit 130; \
}; \
Expand All @@ -184,33 +202,38 @@ dev: install-ui install-air setup-workspace $(if $(DEBUG),install-delve) ## Star
$(ECHO) "$(YELLOW)Starting UI development server...$(NC)"; \
$(USE_NODE); if [ -n "$(DISABLE_PROFILER)" ]; then \
$(ECHO) "$(CYAN)DevProfiler disabled for testing$(NC)"; \
cd ui && BIFROST_DISABLE_PROFILER=1 npm run dev & \
(cd ui && BIFROST_DISABLE_PROFILER=1 npm run dev) & \
else \
cd ui && npm run dev & \
(cd ui && npm run dev) & \
fi; \
ui_pid="$$!"; \
$(ECHO) "$(YELLOW)[make dev] UI dev server started with pid $$ui_pid$(NC)"; \
sleep 3; \
$(ECHO) "$(YELLOW)Starting API server with UI proxy...$(NC)"; \
$(MAKE) setup-workspace >/dev/null; \
if [ -n "$(DEBUG)" ]; then \
$(ECHO) "$(CYAN)Starting with air + delve debugger on port 2345...$(NC)"; \
$(ECHO) "$(YELLOW)Attach your debugger to localhost:2345$(NC)"; \
cd transports/bifrost-http && BIFROST_UI_DEV=true air -c .air.debug.toml -- \
(cd transports/bifrost-http && BIFROST_UI_DEV=true air -c .air.debug.toml -- \
-host "$(HOST)" \
-port "$(PORT)" \
-log-style "$(LOG_STYLE)" \
-log-level "$(LOG_LEVEL)" \
$(if $(PROMETHEUS_LABELS),-prometheus-labels "$(PROMETHEUS_LABELS)") \
$(if $(APP_DIR),-app-dir "$(abspath $(APP_DIR))") & \
$(if $(APP_DIR),-app-dir "$(abspath $(APP_DIR))")) & \
else \
cd transports/bifrost-http && BIFROST_UI_DEV=true air -c .air.toml -- \
(cd transports/bifrost-http && BIFROST_UI_DEV=true air -c .air.toml -- \
-host "$(HOST)" \
-port "$(PORT)" \
-log-style "$(LOG_STYLE)" \
-log-level "$(LOG_LEVEL)" \
$(if $(PROMETHEUS_LABELS),-prometheus-labels "$(PROMETHEUS_LABELS)") \
$(if $(APP_DIR),-app-dir "$(abspath $(APP_DIR))") & \
$(if $(APP_DIR),-app-dir "$(abspath $(APP_DIR))")) & \
fi; \
while [ "$$(jobs -r | wc -l | tr -d ' ')" -eq 2 ]; do sleep 1; done; \
api_pid="$$!"; \
$(ECHO) "$(YELLOW)[make dev] API dev server started with pid $$api_pid$(NC)"; \
while kill -0 "$$ui_pid" 2>/dev/null && kill -0 "$$api_pid" 2>/dev/null; do sleep 1; done; \
$(ECHO) "$(YELLOW)[make dev] one of the dev processes exited; running cleanup...$(NC)"; \
cleanup; \
exit 1

Expand Down Expand Up @@ -247,9 +270,9 @@ dev-pulse: install-ui install-pulse setup-workspace $(if $(DEBUG),install-delve)
$(ECHO) "$(YELLOW)Starting UI development server...$(NC)"; \
$(USE_NODE); if [ -n "$(DISABLE_PROFILER)" ]; then \
$(ECHO) "$(CYAN)DevProfiler disabled for testing$(NC)"; \
cd ui && BIFROST_DISABLE_PROFILER=1 npm run dev & \
(cd ui && BIFROST_DISABLE_PROFILER=1 npm run dev) & \
else \
cd ui && npm run dev & \
(cd ui && npm run dev) & \
fi; \
sleep 3; \
$(ECHO) "$(YELLOW)Starting API server with UI proxy...$(NC)"; \
Expand Down
Loading