@@ -20,10 +20,14 @@ use plugins::{CodeExecutionRequest, ExecutionResult, LanguageInfo, PluginManager
2020use std:: fs;
2121use std:: process:: { Command , Stdio } ;
2222use std:: time:: { SystemTime , UNIX_EPOCH } ;
23- use tauri:: State ;
23+ use tauri:: { AppHandle , Emitter , State } ;
2424use tokio:: sync:: Mutex ;
2525use uuid:: Uuid ;
2626
27+ use std:: io:: { BufRead , BufReader } ;
28+ use std:: sync:: mpsc;
29+ use std:: thread;
30+
2731type ExecutionHistory = Mutex < Vec < ExecutionResult > > ;
2832type PluginManagerState = Mutex < PluginManager > ;
2933
@@ -33,6 +37,7 @@ async fn execute_code(
3337 request : CodeExecutionRequest ,
3438 history : State < ' _ , ExecutionHistory > ,
3539 plugin_manager : State < ' _ , PluginManagerState > ,
40+ app : AppHandle ,
3641) -> Result < ExecutionResult , String > {
3742 info ! ( "执行代码 -> 调用插件 [ {} ] 开始" , request. language) ;
3843 let manager = plugin_manager. lock ( ) . await ;
@@ -62,7 +67,6 @@ async fn execute_code(
6267 . map_err ( |e| format ! ( "Failed to write temporary file: {}" , e) ) ?;
6368
6469 let start_time = std:: time:: Instant :: now ( ) ;
65- let mut _last_error: String = String :: new ( ) ;
6670
6771 let cmd = plugin. get_command ( None ) ;
6872 let args = plugin. get_execute_args ( file_path. to_str ( ) . unwrap ( ) ) ;
@@ -73,14 +77,23 @@ async fn execute_code(
7377 args. join( " " )
7478 ) ;
7579
76- let output = Command :: new ( & cmd)
77- . args ( args)
80+ // 发送执行开始事件
81+ let _ = app. emit (
82+ "code-execution-start" ,
83+ serde_json:: json!( {
84+ "language" : request. language
85+ } ) ,
86+ ) ;
87+
88+ // 启动子进程
89+ let mut child = match Command :: new ( & cmd)
90+ . args ( & args)
7891 . stdout ( Stdio :: piped ( ) )
7992 . stderr ( Stdio :: piped ( ) )
80- . output ( ) ;
81-
82- match output {
83- Ok ( output ) => {
93+ . spawn ( )
94+ {
95+ Ok ( child ) => child ,
96+ Err ( e ) => {
8497 let execution_time = start_time. elapsed ( ) . as_millis ( ) ;
8598 let timestamp = SystemTime :: now ( )
8699 . duration_since ( UNIX_EPOCH )
@@ -90,66 +103,209 @@ async fn execute_code(
90103 // 清理临时文件
91104 let _ = fs:: remove_file ( & file_path) ;
92105
93- let stdout = String :: from_utf8_lossy ( & output. stdout ) . to_string ( ) ;
94- let stderr = String :: from_utf8_lossy ( & output. stderr ) . to_string ( ) ;
95-
96- let mut result = ExecutionResult {
97- success : output. status . success ( ) ,
98- stdout,
99- stderr,
106+ // 发送执行完成事件
107+ let _ = app. emit (
108+ "code-execution-complete" ,
109+ serde_json:: json!( {
110+ "language" : request. language,
111+ "success" : false
112+ } ) ,
113+ ) ;
114+
115+ error ! ( "执行代码 -> 调用插件 [ {} ] 失败: {}" , request. language, e) ;
116+ return Ok ( ExecutionResult {
117+ success : false ,
118+ stdout : String :: new ( ) ,
119+ stderr : format ! (
120+ "{} interpreter not found. Please install {} and ensure it's in your PATH.\n \n Error: {}" ,
121+ request. language, request. language, e
122+ ) ,
100123 execution_time,
101124 timestamp,
102- language : request. language . clone ( ) ,
103- } ;
125+ language : request. language ,
126+ } ) ;
127+ }
128+ } ;
104129
105- // 后处理
106- let _ = plugin . post_execute_hook ( & mut result ) ;
130+ let stdout = child . stdout . take ( ) . unwrap ( ) ;
131+ let stderr = child . stderr . take ( ) . unwrap ( ) ;
107132
108- // 添加到执行历史
109- drop ( manager) ; // 释放插件管理器锁
110- let mut history_guard = history. lock ( ) . await ;
111- history_guard. push ( result. clone ( ) ) ;
133+ let ( stdout_tx, stdout_rx) = mpsc:: channel ( ) ;
134+ let ( stderr_tx, stderr_rx) = mpsc:: channel ( ) ;
112135
113- // 保持历史记录不超过100条
114- if history_guard. len ( ) > 100 {
115- history_guard. remove ( 0 ) ;
136+ // 读取 stdout
137+ thread:: spawn ( move || {
138+ let reader = BufReader :: new ( stdout) ;
139+ for line in reader. lines ( ) {
140+ if let Ok ( line) = line {
141+ if stdout_tx. send ( line) . is_err ( ) {
142+ break ;
143+ }
116144 }
145+ }
146+ } ) ;
147+
148+ // 读取 stderr
149+ thread:: spawn ( move || {
150+ let reader = BufReader :: new ( stderr) ;
151+ for line in reader. lines ( ) {
152+ if let Ok ( line) = line {
153+ if stderr_tx. send ( line) . is_err ( ) {
154+ break ;
155+ }
156+ }
157+ }
158+ } ) ;
159+
160+ let mut stdout_lines = Vec :: new ( ) ;
161+ let mut stderr_lines = Vec :: new ( ) ;
117162
118- info ! ( "执行代码 -> 调用插件 [ {} ] 完成" , request. language) ;
119- return Ok ( result) ;
163+ // 设置超时时间
164+ let timeout = std:: time:: Duration :: from_secs ( 3000 ) ;
165+
166+ loop {
167+ // 检查超时
168+ if start_time. elapsed ( ) > timeout {
169+ let _ = child. kill ( ) ;
170+ let _ = child. wait ( ) ; // 等待进程清理
171+
172+ // 清理临时文件
173+ let _ = fs:: remove_file ( & file_path) ;
174+
175+ // 发送超时事件
176+ let _ = app. emit (
177+ "code-execution-timeout" ,
178+ serde_json:: json!( {
179+ "language" : request. language
180+ } ) ,
181+ ) ;
182+
183+ return Err ( "代码执行超时(30秒)" . to_string ( ) ) ;
120184 }
121- Err ( e) => {
122- _last_error = format ! ( "Failed to execute {} - {}" , cmd, e) ;
185+
186+ // 读取并发送 stdout
187+ while let Ok ( line) = stdout_rx. try_recv ( ) {
188+ stdout_lines. push ( line. clone ( ) ) ;
189+ // 发送实时输出事件
190+ let _ = app. emit (
191+ "code-output" ,
192+ serde_json:: json!( {
193+ "type" : "stdout" ,
194+ "content" : line,
195+ "language" : request. language
196+ } ) ,
197+ ) ;
123198 }
124- }
125199
126- // 如果所有命令都失败了
127- let execution_time = start_time. elapsed ( ) . as_millis ( ) ;
128- let timestamp = SystemTime :: now ( )
129- . duration_since ( UNIX_EPOCH )
130- . unwrap ( )
131- . as_secs ( ) ;
132-
133- // 清理临时文件
134- let _ = fs:: remove_file ( & file_path) ;
135-
136- error ! ( "执行代码 -> 调用插件 [ {} ] 失败" , request. language) ;
137- Ok ( ExecutionResult {
138- success : false ,
139- stdout : String :: new ( ) ,
140- stderr : format ! (
141- "{} interpreter not found. Please install {} and ensure it's in your PATH.\n \n Last error: {}\n \n Tried commands: {:?}" ,
142- request. language,
143- request. language,
144- _last_error,
145- plugin
146- . get_command( Some ( file_path. to_str( ) . unwrap( ) ) )
147- . to_string( )
148- ) ,
149- execution_time,
150- timestamp,
151- language : request. language ,
152- } )
200+ // 读取并发送 stderr
201+ while let Ok ( line) = stderr_rx. try_recv ( ) {
202+ stderr_lines. push ( line. clone ( ) ) ;
203+ // 发送实时错误事件
204+ let _ = app. emit (
205+ "code-output" ,
206+ serde_json:: json!( {
207+ "type" : "stderr" ,
208+ "content" : line,
209+ "language" : request. language
210+ } ) ,
211+ ) ;
212+ }
213+
214+ // 检查进程是否结束
215+ match child. try_wait ( ) {
216+ Ok ( Some ( status) ) => {
217+ // 进程已结束,读取剩余输出
218+ while let Ok ( line) = stdout_rx. try_recv ( ) {
219+ stdout_lines. push ( line. clone ( ) ) ;
220+ let _ = app. emit (
221+ "code-output" ,
222+ serde_json:: json!( {
223+ "type" : "stdout" ,
224+ "content" : line,
225+ "language" : request. language
226+ } ) ,
227+ ) ;
228+ }
229+ while let Ok ( line) = stderr_rx. try_recv ( ) {
230+ stderr_lines. push ( line. clone ( ) ) ;
231+ let _ = app. emit (
232+ "code-output" ,
233+ serde_json:: json!( {
234+ "type" : "stderr" ,
235+ "content" : line,
236+ "language" : request. language
237+ } ) ,
238+ ) ;
239+ }
240+
241+ let execution_time = start_time. elapsed ( ) . as_millis ( ) ;
242+ let timestamp = SystemTime :: now ( )
243+ . duration_since ( UNIX_EPOCH )
244+ . unwrap ( )
245+ . as_secs ( ) ;
246+
247+ // 清理临时文件
248+ let _ = fs:: remove_file ( & file_path) ;
249+
250+ let mut result = ExecutionResult {
251+ success : status. success ( ) ,
252+ stdout : stdout_lines. join ( "\n " ) ,
253+ stderr : stderr_lines. join ( "\n " ) ,
254+ execution_time,
255+ timestamp,
256+ language : request. language . clone ( ) ,
257+ } ;
258+
259+ // 后处理
260+ let _ = plugin. post_execute_hook ( & mut result) ;
261+
262+ // 发送执行完成事件
263+ let _ = app. emit (
264+ "code-execution-complete" ,
265+ serde_json:: json!( {
266+ "language" : request. language,
267+ "success" : result. success,
268+ "execution_time" : result. execution_time
269+ } ) ,
270+ ) ;
271+
272+ // 添加到执行历史
273+ drop ( manager) ; // 释放插件管理器锁
274+ let mut history_guard = history. lock ( ) . await ;
275+ history_guard. push ( result. clone ( ) ) ;
276+
277+ // 保持历史记录不超过100条
278+ if history_guard. len ( ) > 100 {
279+ history_guard. remove ( 0 ) ;
280+ }
281+
282+ info ! ( "执行代码 -> 调用插件 [ {} ] 完成" , request. language) ;
283+ return Ok ( result) ;
284+ }
285+ Ok ( None ) => {
286+ // 进程仍在运行,短暂休眠
287+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_millis ( 100 ) ) . await ;
288+ }
289+ Err ( e) => {
290+ let _ = child. kill ( ) ;
291+ let _ = child. wait ( ) ;
292+
293+ // 清理临时文件
294+ let _ = fs:: remove_file ( & file_path) ;
295+
296+ // 发送执行错误事件
297+ let _ = app. emit (
298+ "code-execution-error" ,
299+ serde_json:: json!( {
300+ "language" : request. language,
301+ "error" : e. to_string( )
302+ } ) ,
303+ ) ;
304+
305+ return Err ( format ! ( "检查进程状态失败: {}" , e) ) ;
306+ }
307+ }
308+ }
153309}
154310
155311// 通用的环境信息获取函数
0 commit comments