Files
hakorune/debug_socketbox.rs

192 lines
6.7 KiB
Rust
Raw Normal View History

🚨 Critical Issue #76: SocketBox Method Call Deadlock Investigation ## 🎯 Problem Identification Complete - SocketBox method calls (bind, isServer, toString) cause infinite blocking - Root cause: Method resolution pipeline deadlock before execute_socket_method - Other Box types (ArrayBox, StringBox, MapBox) work normally - Arc<Mutex> reference sharing confirmed working (Arc addresses match = true) ## 🔧 Debug Infrastructure Added - Comprehensive debug logging in socket_box.rs (bind, isServer, clone, toString) - Method call tracing in http_methods.rs - Deadlock detection points identified at interpreter expressions.rs:462-464 ## 📋 Issue #76 Created for Copilot Investigation - Systematic root cause analysis requirements (Architecture→Parser→Runtime levels) - Comprehensive test cases: minimal/comprehensive/comparison scenarios - Strict prohibition of band-aid fixes - architectural analysis required - Hypothesis: Multiple Arc<Mutex> combinations causing circular deadlock ## 🧪 Test Suite Added - test_socket_deadlock_minimal.nyash: Minimal reproduction case - test_socket_methods_comprehensive.nyash: All methods deadlock verification - test_other_boxes_working.nyash: Normal Box operation confirmation - SOCKETBOX_ISSUE_REPRODUCTION.md: Complete reproduction guide ## 📊 Impact Assessment - Phase 9 HTTP server implementation completely blocked - SocketBox functionality entirely non-functional - Critical blocker for production readiness - Requires immediate systematic investigation 🔥 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-14 20:55:33 +09:00
// 🔍 デバッグ版SocketBox - 全操作を詳細ログ出力
use std::sync::{Arc, Mutex};
use std::fs::OpenOptions;
use std::io::Write;
// デバッグログをファイルに出力
fn debug_log(message: &str) {
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis();
let log_message = format!("[{}] {}\n", timestamp, message);
if let Ok(mut file) = OpenOptions::new()
.create(true)
.append(true)
.open("debug_socketbox.log")
{
let _ = file.write_all(log_message.as_bytes());
let _ = file.flush();
}
// コンソールにも出力
print!("{}", log_message);
}
#[derive(Debug)]
pub struct DebugSocketBox {
id: u64,
listener: Arc<Mutex<Option<std::net::TcpListener>>>,
is_server: Arc<Mutex<bool>>,
}
impl DebugSocketBox {
pub fn new() -> Self {
let id = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
let instance = Self {
id,
listener: Arc::new(Mutex::new(None)),
is_server: Arc::new(Mutex::new(false)),
};
debug_log(&format!("🆕 NEW SocketBox created: id={}, is_server_ptr={:p}",
instance.id, &*instance.is_server));
instance
}
pub fn bind(&self, addr: &str, port: &str) -> bool {
debug_log(&format!("🔗 BIND called on id={}, is_server_ptr={:p}",
self.id, &*self.is_server));
let socket_addr = format!("{}:{}", addr, port);
debug_log(&format!("🔗 BIND address: {}", socket_addr));
match std::net::TcpListener::bind(&socket_addr) {
Ok(listener) => {
// listener設定
match self.listener.lock() {
Ok(mut listener_guard) => {
*listener_guard = Some(listener);
debug_log(&format!("✅ BIND listener set successfully on id={}", self.id));
},
Err(e) => {
debug_log(&format!("❌ BIND listener lock failed: {:?}", e));
return false;
}
}
// is_server=true設定
debug_log(&format!("🔧 BIND setting is_server=true on id={}, ptr={:p}",
self.id, &*self.is_server));
match self.is_server.lock() {
Ok(mut is_server_guard) => {
let old_value = *is_server_guard;
*is_server_guard = true;
debug_log(&format!("✅ BIND is_server changed: {} -> true on id={}",
old_value, self.id));
},
Err(e) => {
debug_log(&format!("❌ BIND is_server lock failed: {:?}", e));
}
}
debug_log(&format!("🎉 BIND completed successfully on id={}", self.id));
true
},
Err(e) => {
debug_log(&format!("❌ BIND failed: {:?}", e));
false
}
}
}
pub fn is_server(&self) -> bool {
debug_log(&format!("❓ IS_SERVER called on id={}, ptr={:p}",
self.id, &*self.is_server));
match self.is_server.lock() {
Ok(is_server_guard) => {
let value = *is_server_guard;
debug_log(&format!("📖 IS_SERVER result: {} on id={}", value, self.id));
value
},
Err(e) => {
debug_log(&format!("❌ IS_SERVER lock failed: {:?}", e));
false
}
}
}
}
impl Clone for DebugSocketBox {
fn clone(&self) -> Self {
debug_log(&format!("🔄 CLONE called on id={}", self.id));
debug_log(&format!("🔄 CLONE original is_server_ptr={:p}", &*self.is_server));
let new_id = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
let cloned = Self {
id: new_id, // 新しいID
listener: Arc::clone(&self.listener),
is_server: Arc::clone(&self.is_server), // ✅ Arc共有
};
debug_log(&format!("🔄 CLONE created: old_id={} -> new_id={}", self.id, cloned.id));
debug_log(&format!("🔄 CLONE new is_server_ptr={:p}", &*cloned.is_server));
debug_log(&format!("🔄 CLONE Arc共有確認: {} == {}",
Arc::as_ptr(&self.is_server) as *const _ as usize,
Arc::as_ptr(&cloned.is_server) as *const _ as usize));
cloned
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_debug_socketbox() {
// ログファイルをクリア
std::fs::write("debug_socketbox.log", "").unwrap();
debug_log("🚀 === DEBUG TEST START ===");
// Step 1: 作成
let socket = DebugSocketBox::new();
debug_log(&format!("Step 1 completed: id={}", socket.id));
// Step 2: bind実行
debug_log("🔥 Step 2: BIND execution");
let bind_result = socket.bind("127.0.0.1", "18080");
debug_log(&format!("Step 2 completed: bind_result={}", bind_result));
// Step 3: 状態確認
debug_log("🔥 Step 3: Check state after bind");
let is_server1 = socket.is_server();
debug_log(&format!("Step 3 completed: is_server={}", is_server1));
// Step 4: clone実行
debug_log("🔥 Step 4: CLONE execution");
let socket_cloned = socket.clone();
// Step 5: clone後の状態確認
debug_log("🔥 Step 5: Check state after clone");
let is_server2 = socket_cloned.is_server();
debug_log(&format!("Step 5 completed: cloned is_server={}", is_server2));
// Step 6: 元の状態確認
debug_log("🔥 Step 6: Check original after clone");
let is_server3 = socket.is_server();
debug_log(&format!("Step 6 completed: original is_server={}", is_server3));
debug_log("🎉 === DEBUG TEST COMPLETED ===");
assert!(bind_result, "bind should succeed");
assert!(is_server1, "is_server should be true after bind");
assert!(is_server2, "cloned is_server should be true (shared Arc)");
assert!(is_server3, "original is_server should still be true");
}
}