@@ -12,42 +12,37 @@ 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 {
3634 try
3735 {
38- return await _executor . ExecuteAsync ( async ( ) =>
39- {
40- return await InnerRunCode ( codeScript , options , cancellationToken ) ;
41- } , cancellationToken : cancellationToken ) ;
36+ return InnerRunWithLock ( codeScript , options , cancellationToken ) ;
4237 }
4338 catch ( Exception ex )
4439 {
45- _logger . LogError ( ex , "Error when using code script executor ." ) ;
40+ _logger . LogError ( ex , $ "Error when using code script with { nameof ( SemaphoreSlim ) } .") ;
4641 return new ( ) { ErrorMsg = ex . Message } ;
4742 }
4843 }
4944
50- return await InnerRunCode ( codeScript , options , cancellationToken ) ;
45+ return InnerRunCode ( codeScript , options , cancellationToken ) ;
5146 }
5247
5348 public async Task < CodeGenerationResult > GenerateCodeScriptAsync ( string text , CodeGenerationOptions ? options = null )
@@ -105,7 +100,30 @@ public async Task<CodeGenerationResult> GenerateCodeScriptAsync(string text, Cod
105100
106101
107102 #region Private methods
108- private async Task < CodeInterpretResponse > InnerRunCode ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
103+ private CodeInterpretResponse InnerRunWithLock ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
104+ {
105+ var lockAcquired = false ;
106+ try
107+ {
108+ _semLock . Wait ( cancellationToken ) ;
109+ lockAcquired = true ;
110+ return InnerRunCode ( codeScript , options , cancellationToken ) ;
111+ }
112+ catch ( Exception ex )
113+ {
114+ _logger . LogError ( ex , $ "Error in { nameof ( InnerRunWithLock ) } ") ;
115+ return new ( ) { ErrorMsg = ex . Message } ;
116+ }
117+ finally
118+ {
119+ if ( lockAcquired )
120+ {
121+ _semLock . Release ( ) ;
122+ }
123+ }
124+ }
125+
126+ private CodeInterpretResponse InnerRunCode ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
109127 {
110128 var response = new CodeInterpretResponse ( ) ;
111129 var scriptName = options ? . ScriptName ?? codeScript . SubstringMax ( 30 ) ;
@@ -116,11 +134,11 @@ private async Task<CodeInterpretResponse> InnerRunCode(string codeScript, CodeIn
116134
117135 if ( options ? . UseProcess == true )
118136 {
119- response = await CoreRunProcess ( codeScript , options , cancellationToken ) ;
137+ response = CoreRunProcess ( codeScript , options , cancellationToken ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
120138 }
121139 else
122140 {
123- response = await CoreRunScript ( codeScript , options , cancellationToken ) ;
141+ response = CoreRunScript ( codeScript , options , cancellationToken ) ;
124142 }
125143
126144 _logger . LogWarning ( $ "End running python code script in { Provider } : { scriptName } ") ;
@@ -141,7 +159,7 @@ private async Task<CodeInterpretResponse> InnerRunCode(string codeScript, CodeIn
141159 }
142160 }
143161
144- private async Task < CodeInterpretResponse > CoreRunScript ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
162+ private CodeInterpretResponse CoreRunScript ( string codeScript , CodeInterpretOptions ? options = null , CancellationToken cancellationToken = default )
145163 {
146164 cancellationToken . ThrowIfCancellationRequested ( ) ;
147165
@@ -161,21 +179,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
161179
162180 try
163181 {
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-
179182 // Redirect standard output/error to capture it
180183 dynamic outIO = io . StringIO ( ) ;
181184 dynamic errIO = io . StringIO ( ) ;
@@ -206,8 +209,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
206209 }
207210 sys . argv = list ;
208211
209- cancellationToken . ThrowIfCancellationRequested ( ) ;
210-
211212 // Execute Python script
212213 PythonEngine . Exec ( codeScript , globals ) ;
213214
@@ -217,8 +218,6 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
217218 var stdout = outIO . getvalue ( ) ? . ToString ( ) as string ;
218219 var stderr = errIO . getvalue ( ) ? . ToString ( ) as string ;
219220
220- cancellationToken . ThrowIfCancellationRequested ( ) ;
221-
222221 return new CodeInterpretResponse
223222 {
224223 Result = stdout ? . TrimEnd ( '\r ' , '\n ' ) ?? string . Empty ,
@@ -237,10 +236,10 @@ private async Task<CodeInterpretResponse> CoreRunScript(string codeScript, CodeI
237236 sys . stderr = sys . __stderr__ ;
238237 sys . argv = new PyList ( ) ;
239238 }
240- } ;
239+ }
241240 } , cancellationToken ) ;
242241
243- return await execTask . WaitAsync ( cancellationToken ) ;
242+ return execTask . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) . GetAwaiter ( ) . GetResult ( ) ;
244243 }
245244
246245
0 commit comments