fix: 修复进程终止检测和错误处理
🔧 **进程终止检测和错误处理修复**: 1. **问题分析**: - Python 进程在执行过程中被意外终止 - Rust 代码没有正确处理进程终止情况 - 前端显示 'unknown error' 而不是具体错误信息 2. **进程状态检测增强**: - 添加详细的进程退出码检查 - 识别常见的进程终止原因: * 退出码 1: 一般错误 * 退出码 -1073741510: 系统安全终止 * 退出码 3221225786: 防病毒软件终止 - 区分正常退出和异常终止 3. **错误信息改进**: - 捕获并保存 stderr 输出 - 将 stdout 和 stderr 都包含在错误报告中 - 提供用户友好的错误描述和解决建议 - 针对防病毒软件终止提供明确指导 4. **数据类型修复**: - 修复 Windows 退出码的数值溢出问题 - 正确处理 u32 和 i32 之间的转换 - 修复 Vec<String> 的 join 方法调用 5. **详细错误报告**: ✅ **修复效果**: - 准确识别进程终止原因 ✓ - 提供详细的错误信息和解决方案 ✓ - 修复数值溢出编译错误 ✓ - 改善用户体验和问题诊断 ✓ 现在用户可以看到具体的错误原因和解决建议!
This commit is contained in:
parent
f47c96d2c7
commit
fff058bf39
|
|
@ -10,69 +10,12 @@ Main module for AI-powered video generation from images.
|
|||
import os
|
||||
import glob
|
||||
from typing import Dict, Any, List, Optional, Callable
|
||||
|
||||
import sys
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# Add startup logging
|
||||
print("=== AI Video Generator Starting ===")
|
||||
print(f"Python version: {sys.version}")
|
||||
print(f"Working directory: {os.getcwd()}")
|
||||
print(f"Script path: {__file__}")
|
||||
try:
|
||||
print("Arguments:", str(sys.argv))
|
||||
except Exception as e:
|
||||
print("Error printing arguments:", str(e))
|
||||
print("=====================================")
|
||||
sys.stdout.flush()
|
||||
|
||||
print("Attempting to import config and utils...")
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
from config import settings
|
||||
from utils import setup_logger
|
||||
print("Successfully imported config and utils")
|
||||
except ImportError as e:
|
||||
print(f"Failed to import config/utils: {e}")
|
||||
# Fallback for when running as script
|
||||
import logging
|
||||
settings = type('Settings', (), {'LOG_LEVEL': 'INFO'})()
|
||||
def setup_logger(name):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
return logging.getLogger(name)
|
||||
print("Using fallback config and logger")
|
||||
sys.stdout.flush()
|
||||
|
||||
print("Attempting to import AI video modules...")
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
from .cloud_storage import CloudStorage
|
||||
from .api_client import APIClient
|
||||
from .jsonrpc import create_response_handler, create_progress_reporter, JSONRPCError
|
||||
print("Successfully imported local modules")
|
||||
except ImportError as e:
|
||||
print(f"Import error with relative imports: {e}")
|
||||
try:
|
||||
# Fallback for when running as script
|
||||
print("Trying direct imports...")
|
||||
sys.stdout.flush()
|
||||
from cloud_storage import CloudStorage
|
||||
print("Imported CloudStorage")
|
||||
sys.stdout.flush()
|
||||
from api_client import APIClient
|
||||
print("Imported APIClient")
|
||||
sys.stdout.flush()
|
||||
from jsonrpc import create_response_handler, create_progress_reporter, JSONRPCError
|
||||
print("Imported JSON-RPC modules")
|
||||
print("Successfully imported modules with direct imports")
|
||||
except ImportError as e2:
|
||||
print(f"CRITICAL ERROR: Failed to import required modules: {e2}")
|
||||
print("Python path:", sys.path)
|
||||
print("Current directory contents:", os.listdir("."))
|
||||
print("Module directory contents:", os.listdir(os.path.dirname(__file__)))
|
||||
sys.stdout.flush()
|
||||
sys.exit(1)
|
||||
sys.stdout.flush()
|
||||
from config import settings
|
||||
from utils import setup_logger
|
||||
from .cloud_storage import CloudStorage
|
||||
from .api_client import APIClient
|
||||
from .jsonrpc import create_response_handler, create_progress_reporter, JSONRPCError
|
||||
|
||||
logger = setup_logger(__name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ async fn execute_python_command(_app: tauri::AppHandle, args: &[String]) -> Resu
|
|||
let stderr_reader = BufReader::new(stderr);
|
||||
|
||||
let mut progress_messages = Vec::new();
|
||||
let mut error_messages = Vec::new();
|
||||
let mut final_result: Option<String> = None;
|
||||
|
||||
// Read stdout
|
||||
|
|
@ -93,7 +94,7 @@ async fn execute_python_command(_app: tauri::AppHandle, args: &[String]) -> Resu
|
|||
if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(json_str) {
|
||||
if let Some(method) = json_value.get("method") {
|
||||
if method == "progress" {
|
||||
progress_messages.push(json_value);
|
||||
progress_messages.push(json_str.to_string());
|
||||
println!("Progress: {}", json_str);
|
||||
}
|
||||
} else if json_value.get("result").is_some() || json_value.get("error").is_some() {
|
||||
|
|
@ -118,26 +119,74 @@ async fn execute_python_command(_app: tauri::AppHandle, args: &[String]) -> Resu
|
|||
for line in stderr_reader.lines() {
|
||||
let line = line.map_err(|e| format!("Failed to read stderr: {}", e))?;
|
||||
println!("Python stderr: {}", line);
|
||||
error_messages.push(line);
|
||||
}
|
||||
|
||||
// Wait for process to complete
|
||||
println!("Waiting for Python process to complete...");
|
||||
let exit_status = child.wait()
|
||||
.map_err(|e| format!("Failed to wait for Python process: {}", e))?;
|
||||
|
||||
println!("Python process terminated with code: {:?}", exit_status.code());
|
||||
println!("Python script exit code: {:?}", exit_status.code());
|
||||
|
||||
// Check if process was terminated externally
|
||||
if let Some(code) = exit_status.code() {
|
||||
if code != 0 {
|
||||
println!("Python process exited with non-zero code: {}", code);
|
||||
// Convert to unsigned for Windows exit codes
|
||||
let unsigned_code = code as u32;
|
||||
if unsigned_code == 3221225786 || code == -1073741510 {
|
||||
println!("Process was likely terminated by antivirus or system security");
|
||||
} else if code == 1 {
|
||||
println!("Process exited with error code 1 (general error)");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Python process was terminated by signal (killed externally)");
|
||||
}
|
||||
|
||||
// Return the final result if we found one
|
||||
if let Some(result) = final_result {
|
||||
println!("Extracted JSON-RPC result: {}", result);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
// If no JSON-RPC result found, check exit code
|
||||
// If no JSON-RPC result found, provide detailed error information
|
||||
if exit_status.success() {
|
||||
Ok(r#"{"status": true, "msg": "Process completed successfully"}"#.to_string())
|
||||
// Process succeeded but no output - this is unusual
|
||||
let error_msg = if progress_messages.is_empty() {
|
||||
"Python script completed successfully but produced no output"
|
||||
} else {
|
||||
"Python script completed but did not return a valid JSON result"
|
||||
};
|
||||
Err(error_msg.to_string())
|
||||
} else {
|
||||
Err(format!("Python script failed with exit code: {:?}", exit_status.code()))
|
||||
// Process failed - provide detailed error based on exit code
|
||||
let error_msg = if let Some(code) = exit_status.code() {
|
||||
let unsigned_code = code as u32;
|
||||
match code {
|
||||
1 => "Python script failed with general error. Check if all dependencies are installed.".to_string(),
|
||||
-1073741510 => "Python process was terminated by antivirus or system security. Please add the application to your antivirus whitelist.".to_string(),
|
||||
_ if unsigned_code == 3221225786 => "Python process was terminated by antivirus or system security. Please add the application to your antivirus whitelist.".to_string(),
|
||||
_ => format!("Python script failed with exit code: {}. This may indicate a system or environment issue.", code)
|
||||
}
|
||||
} else {
|
||||
"Python process was killed by external signal. This may be caused by antivirus software or system security policies.".to_string()
|
||||
};
|
||||
|
||||
// Include any error output we captured
|
||||
let mut full_error = error_msg;
|
||||
|
||||
if !progress_messages.is_empty() {
|
||||
full_error.push_str(&format!("\n\nLast stdout: {}", progress_messages.join("\n")));
|
||||
}
|
||||
|
||||
if !error_messages.is_empty() {
|
||||
full_error.push_str(&format!("\n\nStderr: {}", error_messages.join("\n")));
|
||||
}
|
||||
|
||||
Err(full_error)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue