v0.7.15 - Fixed race condition in subscription management causing intermittent core dumps and format truncation warning

This commit is contained in:
Your Name
2025-10-14 11:34:55 -04:00
parent 670329700c
commit 29680f0ee8
8 changed files with 77 additions and 53 deletions

View File

@@ -174,7 +174,7 @@
<!-- DATABASE STATISTICS Section --> <!-- DATABASE STATISTICS Section -->
<div class="section"> <div class="section" id="databaseStatisticsSection" style="display: none;">
<div class="section-header"> <div class="section-header">
<h2>DATABASE STATISTICS</h2> <h2>DATABASE STATISTICS</h2>
</div> </div>

View File

@@ -607,11 +607,13 @@
function updateAdminSectionsVisibility() { function updateAdminSectionsVisibility() {
const divConfig = document.getElementById('div_config'); const divConfig = document.getElementById('div_config');
const authRulesSection = document.getElementById('authRulesSection'); const authRulesSection = document.getElementById('authRulesSection');
const databaseStatisticsSection = document.getElementById('databaseStatisticsSection');
const nip17DMSection = document.getElementById('nip17DMSection'); const nip17DMSection = document.getElementById('nip17DMSection');
const shouldShow = isLoggedIn && isRelayConnected; const shouldShow = isLoggedIn && isRelayConnected;
if (divConfig) divConfig.style.display = shouldShow ? 'block' : 'none'; if (divConfig) divConfig.style.display = shouldShow ? 'block' : 'none';
if (authRulesSection) authRulesSection.style.display = shouldShow ? 'block' : 'none'; if (authRulesSection) authRulesSection.style.display = shouldShow ? 'block' : 'none';
if (databaseStatisticsSection) databaseStatisticsSection.style.display = shouldShow ? 'block' : 'none';
if (nip17DMSection) nip17DMSection.style.display = shouldShow ? 'block' : 'none'; if (nip17DMSection) nip17DMSection.style.display = shouldShow ? 'block' : 'none';
} }
@@ -2131,7 +2133,7 @@
const originalShowMainInterface = showMainInterface; const originalShowMainInterface = showMainInterface;
showMainInterface = function () { showMainInterface = function () {
originalShowMainInterface(); originalShowMainInterface();
showAuthRulesSection(); // Removed showAuthRulesSection() call - visibility now handled by updateAdminSectionsVisibility()
}; };
// Auth rules event handlers // Auth rules event handlers
@@ -3532,6 +3534,9 @@
// Initialize login/logout button state // Initialize login/logout button state
updateLoginLogoutButton(); updateLoginLogoutButton();
// Ensure admin sections are hidden by default on page load
updateAdminSectionsVisibility();
setTimeout(() => { setTimeout(() => {
initializeApp(); initializeApp();
// Enhance SimplePool for testing after initialization // Enhance SimplePool for testing after initialization

View File

@@ -1,8 +1,7 @@
#!/bin/bash #!/bin/bash
# C-Relay Static Binary Deployment Script # C-Relay Static Binary Deployment Script
# Deploys build/c_relay_static_x86_64 to server via sshlt # Deploys build/c_relay_static_x86_64 to server via ssh
# Usage: ./deploy_static.sh [--debug-level=N] [-d=N]
set -e set -e
@@ -11,44 +10,6 @@ LOCAL_BINARY="build/c_relay_static_x86_64"
REMOTE_BINARY_PATH="/usr/local/bin/c_relay/c_relay" REMOTE_BINARY_PATH="/usr/local/bin/c_relay/c_relay"
SERVICE_NAME="c-relay" SERVICE_NAME="c-relay"
# Default debug level
DEBUG_LEVEL=0
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
--debug-level=*)
DEBUG_LEVEL="${1#*=}"
shift
;;
-d=*)
DEBUG_LEVEL="${1#*=}"
shift
;;
--debug-level)
DEBUG_LEVEL="$2"
shift 2
;;
-d)
DEBUG_LEVEL="$2"
shift 2
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--debug-level=N] [-d=N]"
exit 1
;;
esac
done
# Validate debug level
if ! [[ "$DEBUG_LEVEL" =~ ^[0-5]$ ]]; then
echo "Error: Debug level must be 0-5, got: $DEBUG_LEVEL"
exit 1
fi
echo "Deploying with debug level: $DEBUG_LEVEL"
# Create backup # Create backup
ssh ubuntu@laantungir.com "sudo cp '$REMOTE_BINARY_PATH' '${REMOTE_BINARY_PATH}.backup.$(date +%Y%m%d_%H%M%S)'" 2>/dev/null || true ssh ubuntu@laantungir.com "sudo cp '$REMOTE_BINARY_PATH' '${REMOTE_BINARY_PATH}.backup.$(date +%Y%m%d_%H%M%S)'" 2>/dev/null || true
@@ -60,9 +21,6 @@ ssh ubuntu@laantungir.com "sudo mv '/tmp/c_relay.tmp' '$REMOTE_BINARY_PATH'"
ssh ubuntu@laantungir.com "sudo chown c-relay:c-relay '$REMOTE_BINARY_PATH'" ssh ubuntu@laantungir.com "sudo chown c-relay:c-relay '$REMOTE_BINARY_PATH'"
ssh ubuntu@laantungir.com "sudo chmod +x '$REMOTE_BINARY_PATH'" ssh ubuntu@laantungir.com "sudo chmod +x '$REMOTE_BINARY_PATH'"
# Update systemd service environment variable
ssh ubuntu@laantungir.com "sudo sed -i 's/Environment=DEBUG_LEVEL=.*/Environment=DEBUG_LEVEL=$DEBUG_LEVEL/' /etc/systemd/system/c-relay.service"
# Reload systemd and restart service # Reload systemd and restart service
ssh ubuntu@laantungir.com "sudo systemctl daemon-reload" ssh ubuntu@laantungir.com "sudo systemctl daemon-reload"
ssh ubuntu@laantungir.com "sudo systemctl restart '$SERVICE_NAME'" ssh ubuntu@laantungir.com "sudo systemctl restart '$SERVICE_NAME'"

40
notes.txt Normal file
View File

@@ -0,0 +1,40 @@
Task Completed
Perfect! The core dump limit is now set correctly. You can see both:
LimitCORE=infinity
LimitCORESoft=infinity
What happens next:
The relay is now configured to generate core dumps when it crashes
Wait for the next crash to occur (based on your logs, it seems to happen intermittently)
When it crashes, the core dump will be automatically captured by systemd
After the next crash, analyze it:
# List all core dumps (most recent first)
sudo coredumpctl list
# View info about the most recent c-relay crash
sudo coredumpctl info c-relay
# Load the core dump in gdb for detailed analysis
sudo coredumpctl gdb c-relay
Inside gdb, run these commands:
(gdb) bt full # Full backtrace with all variables
(gdb) info threads # Show all threads
(gdb) thread apply all bt # Backtrace for all threads
(gdb) frame 0 # Go to crash frame
(gdb) info locals # Show local variables
(gdb) list # Show source code around crash
The backtrace will show you exactly which line of code caused the segmentation fault and the state of all variables at that moment, which should pinpoint whether it's the subscription management issue, buffer overflow, or something else.
You're all set up now - just wait for the next crash and then run the coredumpctl commands to analyze it.
--------------------------
Even simpler: Use this one-liner
# Start relay and immediately attach gdb
cd /usr/local/bin/c_relay
sudo -u c-relay ./c_relay --debug-level=5 & sleep 2 && sudo gdb -p $(pgrep c_relay)

View File

@@ -1 +1 @@
2614899 2798177

File diff suppressed because one or more lines are too long

View File

@@ -622,7 +622,8 @@ int broadcast_event_to_subscriptions(cJSON* event) {
subscription_t* update_sub = g_subscription_manager.active_subscriptions; subscription_t* update_sub = g_subscription_manager.active_subscriptions;
while (update_sub) { while (update_sub) {
if (update_sub->wsi == current_temp->wsi && if (update_sub->wsi == current_temp->wsi &&
strcmp(update_sub->id, current_temp->id) == 0) { strcmp(update_sub->id, current_temp->id) == 0 &&
update_sub->active) { // Add active check to prevent use-after-free
update_sub->events_sent++; update_sub->events_sent++;
break; break;
} }

View File

@@ -516,8 +516,28 @@ static int nostr_relay_callback(struct lws *wsi, enum lws_callback_reasons reaso
if (event_kind == 23456) { if (event_kind == 23456) {
if (admin_result != 0) { if (admin_result != 0) {
char error_result_msg[512]; char error_result_msg[512];
snprintf(error_result_msg, sizeof(error_result_msg), if (admin_error && strlen(admin_error) > 0) {
"ERROR: Kind %d event processing failed: %s", event_kind, admin_error); // Safely truncate admin_error if too long
size_t max_error_len = sizeof(error_result_msg) - 50; // Leave room for prefix
size_t error_len = strlen(admin_error);
if (error_len > max_error_len) {
error_len = max_error_len;
}
char truncated_error[512];
memcpy(truncated_error, admin_error, error_len);
truncated_error[error_len] = '\0';
// Use a safer approach to avoid truncation warning
size_t prefix_len = snprintf(error_result_msg, sizeof(error_result_msg),
"ERROR: Kind %d event processing failed: ", event_kind);
if (prefix_len < sizeof(error_result_msg)) {
size_t remaining = sizeof(error_result_msg) - prefix_len;
strncat(error_result_msg, truncated_error, remaining - 1);
}
} else {
snprintf(error_result_msg, sizeof(error_result_msg),
"ERROR: Kind %d event processing failed", event_kind);
}
DEBUG_ERROR(error_result_msg); DEBUG_ERROR(error_result_msg);
} }
} }