fix: eliminate infinite recursion in TdClientTrait implementation

CRITICAL BUG FIX: Three methods in TdClientTrait impl were calling themselves recursively instead of delegating to actual implementations, causing stack overflow and application panic on startup.

Fixed methods:
1. user_cache_mut() - now returns &mut self.user_cache directly
2. sync_notification_muted_chats() - now delegates to notification_manager.sync_muted_chats()
3. handle_update() - now properly delegates to TdClient::handle_update() using qualified path

This bug caused the app to hang on "Инициализация TDLib..." screen and exit raw mode, displaying escape sequences ("CB52") on key presses when user tried to interact.

Root cause: Introduced in refactoring commit bd5e5be where trait implementations were created but incorrectly delegated to self.method() instead of accessing struct fields directly or using qualified path syntax.

Also added panic hook in main.rs to ensure terminal restoration on panic for better debugging experience.

Impact: Application completely broken - couldn't start. Stack overflow on first update.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-05 12:52:42 +03:00
parent bccf07501f
commit 5f1d715e8f
2 changed files with 15 additions and 6 deletions

View File

@@ -55,14 +55,22 @@ async fn main() -> Result<(), io::Error> {
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
// Ensure terminal restoration on panic
let panic_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |info| {
let _ = disable_raw_mode();
let _ = execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture);
panic_hook(info);
}));
// Create app state
let mut app = App::new(config);
// Запускаем инициализацию TDLib в фоне (только для реального клиента)
let client_id = app.td_client.client_id();
let api_id = app.td_client.api_id;
let api_hash = app.td_client.api_hash.clone();
tokio::spawn(async move {
let _ = tdlib_rs::functions::set_tdlib_parameters(
false, // use_test_dc
@@ -83,7 +91,7 @@ async fn main() -> Result<(), io::Error> {
)
.await;
});
let res = run_app(&mut terminal, &mut app).await;
// Restore terminal

View File

@@ -260,16 +260,17 @@ impl TdClientTrait for TdClient {
}
fn user_cache_mut(&mut self) -> &mut UserCache {
self.user_cache_mut()
&mut self.user_cache
}
// ============ Notification methods ============
fn sync_notification_muted_chats(&mut self) {
self.sync_notification_muted_chats()
self.notification_manager.sync_muted_chats(&self.chat_manager.chats);
}
// ============ Update handling ============
fn handle_update(&mut self, update: Update) {
self.handle_update(update)
// Delegate to the real implementation
TdClient::handle_update(self, update)
}
}