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 <noreply@anthropic.com>
This commit is contained in:
Developer
2026-03-19 22:05:52 -04:00
parent fbcbbf8a43
commit ce8babe62f
+12 -7
View File
@@ -402,27 +402,32 @@ build_domains_section() {
# Also add aliases as separate entries # Also add aliases as separate entries
if [ -n "$server_alias" ]; then if [ -n "$server_alias" ]; then
# Convert space-separated aliases to newline-separated for safe iteration # 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 [ -z "$alias" ] && continue
[ -n "${seen_domains[$alias]:-}" ] && continue [ -n "${seen_domains[$alias]:-}" ] && continue
# Alias points to same document root and logs (inherit status from parent) # 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" 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 seen_domains["$alias"]=1
done done <<< "$(echo "$server_alias" | tr ' ' '\n')"
fi fi
done done
else else
# Fallback for non-cPanel or if userdata not available # 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) # Use here-document instead of pipe to avoid subshell (allows seen_domains updates to persist)
get_user_domains "$user" | while IFS= read -r domain; do while IFS= read -r domain; do
[ -z "$domain" ] && continue [ -z "$domain" ] && continue
[ -n "${seen_domains[$domain]:-}" ] && continue [ -n "${seen_domains[$domain]:-}" ] && continue
local is_primary="no" 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 # Find log path
local log_path="${SYS_LOG_DIR}/${domain}" local log_path="${SYS_LOG_DIR}/${domain}"
@@ -437,7 +442,7 @@ build_domains_section() {
# Simple format for non-cPanel (with status codes) # 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" echo "DOMAIN|$domain|$user||$log_path||$is_primary|local||$http_code|$https_code|$status_summary" >> "$SYSREF_DB"
seen_domains["$domain"]=1 seen_domains["$domain"]=1
done done <<< "$user_domains"
fi fi
done done