@@ -12,42 +12,29 @@ public class PyCodeInterpreter : ICodeProcessor
1212{
1313 private readonly IServiceProvider _services ;
1414 private readonly ILogger < PyCodeInterpreter > _logger ;
15- private readonly CodeScriptExecutor _executor ;
1615 private readonly CodingSettings _settings ;
16+ private static SemaphoreSlim _semLock = new ( initialCount : 1 , maxCount : 1 ) ;
1717
1818 public PyCodeInterpreter (
1919 IServiceProvider services ,
2020 ILogger < PyCodeInterpreter > logger ,
21- CodeScriptExecutor executor ,
2221 CodingSettings settings )
2322 {
2423 _services = services ;
2524 _logger = logger ;
26- _executor = executor ;
2725 _settings = settings ;
2826 }
2927
3028 public string Provider => BuiltInCodeProcessor . PyInterpreter ;
3129
32- public async Task < CodeInterpretResponse > RunAsync ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
30+ public CodeInterpretResponse Run ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
3331 {
3432 if ( options ? . UseLock == true )
3533 {
36- try
37- {
38- return await _executor . ExecuteAsync ( async ( ) =>
39- {
40- return await InnerRunCode ( codeScript , options , cancellationToken ) ;
41- } , cancellationToken : cancellationToken ) ;
42- }
43- catch ( Exception ex )
44- {
45- _logger . LogError ( ex , "Error when using code script executor." ) ;
46- return new ( ) { ErrorMsg = ex . Message } ;
47- }
34+ return InnerRunWithLock ( codeScript , options , cancellationToken ) ;
4835 }
4936
50- return await InnerRunCode ( codeScript , options , cancellationToken ) ;
37+ return InnerRunCode ( codeScript , options , cancellationToken ) ;
5138 }
5239
5340 public async Task < CodeGenerationResult > GenerateCodeScriptAsync ( string text , CodeGenerationOptions ? options = null )
@@ -105,7 +92,30 @@ public async Task<CodeGenerationResult> GenerateCodeScriptAsync(string text, Cod
10592
10693
10794 #region Private methods
108- private async Task < CodeInterpretResponse > InnerRunCode ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
95+ private CodeInterpretResponse InnerRunWithLock ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
96+ {
97+ var lockAcquired = false ;
98+ try
99+ {
100+ _semLock . Wait ( cancellationToken ) ;
101+ lockAcquired = true ;
102+ return InnerRunCode ( codeScript , options , cancellationToken ) ;
103+ }
104+ catch ( Exception ex )
105+ {
106+ _logger . LogError ( ex , $ "Error in { nameof ( InnerRunWithLock ) } ") ;
107+ return new ( ) { ErrorMsg = ex . Message } ;
108+ }
109+ finally
110+ {
111+ if ( lockAcquired )
112+ {
113+ _semLock . Release ( ) ;
114+ }
115+ }
116+ }
117+
118+ private CodeInterpretResponse InnerRunCode ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
109119 {
110120 var response = new CodeInterpretResponse ( ) ;
111121 var scriptName = options ? . ScriptName ?? codeScript . SubstringMax ( 30 ) ;
@@ -116,11 +126,11 @@ private async Task<CodeInterpretResponse> InnerRunCode(string codeScript, CodeIn
116126
117127 if ( options ? . UseProcess == true )
118128 {
119- response = await CoreRunProcess ( codeScript , options , cancellationToken ) ;
129+ response = CoreRunProcess ( codeScript , options , cancellationToken ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
120130 }
121131 else
122132 {
123- response = await CoreRunScript ( codeScript , options , cancellationToken ) ;
133+ response = CoreRunScript ( codeScript , options , cancellationToken ) ;
124134 }
125135
126136 _logger . LogWarning ( $ "End running python code script in { Provider } : { scriptName } ") ;
@@ -141,7 +151,7 @@ private async Task<CodeInterpretResponse> InnerRunCode(string codeScript, CodeIn
141151 }
142152 }
143153
144- private async Task < CodeInterpretResponse > CoreRunScript ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
154+ private CodeInterpretResponse CoreRunScript ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
145155 {
146156 cancellationToken . ThrowIfCancellationRequested ( ) ;
147157
@@ -161,21 +171,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
161171
162172 try
163173 {
164- // Capture the Python thread ID for the current thread executing under the GIL
165- var pythonThreadId = PythonEngine . GetPythonThreadID ( ) ;
166- using var reg = cancellationToken . Register ( ( ) =>
167- {
168- try
169- {
170- PythonEngine . Interrupt ( pythonThreadId ) ;
171- _logger . LogWarning ( $ "Cancellation requested: issued PythonEngine.Interrupt for thread { pythonThreadId } (request { requestId } )") ;
172- }
173- catch ( Exception ex )
174- {
175- _logger . LogError ( ex , "Failed to interrupt Python execution on cancellation." ) ;
176- }
177- } ) ;
178-
179174 // Redirect standard output/error to capture it
180175 dynamic outIO = io . StringIO ( ) ;
181176 dynamic errIO = io . StringIO ( ) ;
@@ -206,8 +201,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
206201 }
207202 sys . argv = list ;
208203
209- cancellationToken . ThrowIfCancellationRequested ( ) ;
210-
211204 // Execute Python script
212205 PythonEngine . Exec ( codeScript , globals ) ;
213206
@@ -217,8 +210,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
217210 var stdout = outIO . getvalue ( ) ? . ToString ( ) as string ;
218211 var stderr = errIO . getvalue ( ) ? . ToString ( ) as string ;
219212
220- cancellationToken . ThrowIfCancellationRequested ( ) ;
221-
222213 return new CodeInterpretResponse
223214 {
224215 Result = stdout ? . TrimEnd ( '\r ' , '\n ' ) ?? string . Empty ,
@@ -237,10 +228,10 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
237228 sys . stderr = sys . __stderr__ ;
238229 sys . argv = new PyList ( ) ;
239230 }
240- } ;
231+ }
241232 } , cancellationToken ) ;
242233
243- return await execTask . WaitAsync ( cancellationToken ) ;
234+ return execTask . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
244235 }
245236
246237
0 commit comments