From ce8babe62fd435261ada5874ac1b363199e660eb Mon Sep 17 00:00:00 2001 From: Developer Date: Thu, 19 Mar 2026 22:05:52 -0400 Subject: [PATCH] CRITICAL FIX: Fix subshell array corruption in domain discovery ISSUE: Pipe-to-while loops created subshells, preventing seen_domains array updates from persisting to parent shell. This caused: 1. Duplicate domains in reference database 2. Database corruption 3. Inefficient double processing of domains FIXES: 1. Lines 416-444: Changed pipe-based while to here-document - BEFORE: get_user_domains "$user" | while IFS= read -r domain; do - AFTER: while IFS= read -r domain; do ... done <<< "$user_domains" - Result: seen_domains updates now persist to parent shell 2. Lines 416-417: Call get_user_domains() only once - BEFORE: Called twice (lines 417 and 420) - AFTER: Called once, stored in $user_domains - Result: No duplicate function calls 3. Line 422: Added check for empty primary_domain - BEFORE: [ "$domain" = "$primary_domain" ] - AFTER: [ -n "$primary_domain" ] && [ "$domain" = "$primary_domain" ] - Result: Handles edge case where user has no domains 4. Lines 405-412: Fixed alias iteration subshell issue - BEFORE: echo ... | tr ... | while IFS= read -r alias; do - AFTER: while IFS= read -r alias; do ... done <<< "$(echo ... | tr ...)" - Result: seen_domains["alias"] updates persist TESTING: - bash -n validates syntax - Logic verified for subshell fix - Array updates will now persist to parent shell Impact: - Reference database no longer corrupted with duplicates - Proper domain deduplication via seen_domains array - Database building now works correctly Co-Authored-By: Claude Haiku 4.5 --- lib/reference-db.sh | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/reference-db.sh b/lib/reference-db.sh index a45026c..aa8ed13 100755 --- a/lib/reference-db.sh +++ b/lib/reference-db.sh @@ -402,27 +402,32 @@ build_domains_section() { # Also add aliases as separate entries if [ -n "$server_alias" ]; then # Convert space-separated aliases to newline-separated for safe iteration - echo "$server_alias" | tr ' ' '\n' | while IFS= read -r alias; do + # Use here-document instead of pipe to avoid subshell + while IFS= read -r alias; do [ -z "$alias" ] && continue [ -n "${seen_domains[$alias]:-}" ] && continue # Alias points to same document root and logs (inherit status from parent) echo "DOMAIN|$alias|$user|$doc_root|$log_path|$php_version|no|alias|$domain|$http_code|$https_code|alias_of_$status_summary" >> "$SYSREF_DB" seen_domains["$alias"]=1 - done + done <<< "$(echo "$server_alias" | tr ' ' '\n')" fi done else # Fallback for non-cPanel or if userdata not available - local primary_domain=$(get_user_domains "$user" | head -1) + local user_domains=$(get_user_domains "$user") + local primary_domain=$(echo "$user_domains" | head -1) - # Use while read to safely iterate over domains (handles spaces) - get_user_domains "$user" | while IFS= read -r domain; do + # Use here-document instead of pipe to avoid subshell (allows seen_domains updates to persist) + while IFS= read -r domain; do [ -z "$domain" ] && continue [ -n "${seen_domains[$domain]:-}" ] && continue local is_primary="no" - [ "$domain" = "$primary_domain" ] && is_primary="yes" + # Only mark as primary if primary_domain is not empty AND matches + if [ -n "$primary_domain" ] && [ "$domain" = "$primary_domain" ]; then + is_primary="yes" + fi # Find log path local log_path="${SYS_LOG_DIR}/${domain}" @@ -437,7 +442,7 @@ build_domains_section() { # Simple format for non-cPanel (with status codes) echo "DOMAIN|$domain|$user||$log_path||$is_primary|local||$http_code|$https_code|$status_summary" >> "$SYSREF_DB" seen_domains["$domain"]=1 - done + done <<< "$user_domains" fi done