@@ -121,45 +121,70 @@ def __make_non_blocking(fd):
121121 return res != 0
122122
123123 def _cmd_process (self , cmd ):
124- cmd = cmd . strip (). replace ( " \n " , ";" )
125- try :
126- self . process . stdin . write (( cmd + " \n " ). encode ( "utf8" ))
127- except :
128- return ''
129- r = self . process . stdout
130- self .process . stdin . flush ()
131- out = bytearray ()
132- foo = None
133- while True :
134- if self . process . poll () is not None :
135- raise RuntimeError ( f"Process terminated unexpectedly trying to run the command { cmd } \n { self . process } " )
124+ # Add a simple mutex-like lock mechanism using threading
125+ import threading
126+ if not hasattr ( self , '_cmd_lock' ):
127+ self . _cmd_lock = threading . Lock ()
128+
129+ # Acquire lock to ensure commands don't interfere with each other
130+ with self ._cmd_lock :
131+ # Ensure pending buffer is cleared before starting a new command to avoid mixing
132+ old_pending = self . pending
133+ self . pending = b""
134+
135+ cmd = cmd . strip (). replace ( " \n " , "; " )
136136 try :
137- null_start = False
138- if len (self .pending ) > 0 :
139- foo = self .pending
140- self .pending = b""
141- else :
142- foo = r .read (4096 )
143- if os .name == "nt" :
144- if foo .startswith (b"\x00 " ):
145- foo = foo [1 :]
146- null_start = True
147- if foo :
148- zro = foo .find (b"\x00 " )
149- if zro != - 1 :
150- out += foo [0 :zro ]
151- if zro < len (foo ):
152- self .pending = foo [zro + 1 :]
137+ self .process .stdin .write ((cmd + "\n " ).encode ("utf8" ))
138+ except :
139+ self .pending = old_pending # Restore pending on failure
140+ return ''
141+
142+ r = self .process .stdout
143+ self .process .stdin .flush ()
144+ out = bytearray ()
145+ foo = None
146+
147+ # First read any pending data from previous commands if exists
148+ if old_pending :
149+ zro = old_pending .find (b"\x00 " )
150+ if zro != - 1 :
151+ # This is a complete response from previous command, process it first
152+ out += old_pending [0 :zro ]
153+ if zro + 1 < len (old_pending ):
154+ self .pending = old_pending [zro + 1 :]
155+ return out .decode ("utf-8" , errors = "ignore" )
156+
157+ # Main read loop for current command
158+ while True :
159+ if self .process .poll () is not None :
160+ raise RuntimeError (f"Process terminated unexpectedly trying to run the command { cmd } \n { self .process } " )
161+ try :
162+ null_start = False
163+ if len (self .pending ) > 0 :
164+ foo = self .pending
165+ self .pending = b""
166+ else :
167+ foo = r .read (4096 )
168+ if os .name == "nt" :
169+ if foo .startswith (b"\x00 " ):
170+ foo = foo [1 :]
171+ null_start = True
172+ if foo :
173+ zro = foo .find (b"\x00 " )
174+ if zro != - 1 :
175+ out += foo [0 :zro ]
176+ if zro + 1 < len (foo ):
177+ self .pending = foo [zro + 1 :]
178+ break
179+ out += foo
180+ elif null_start :
153181 break
154- out += foo
155- elif null_start :
156- break
157182
158- except KeyboardInterrupt as e :
159- raise e
160- except :
161- pass
162- return out .decode ("utf-8" , errors = "ignore" )
183+ except KeyboardInterrupt as e :
184+ raise e
185+ except :
186+ pass
187+ return out .decode ("utf-8" , errors = "ignore" )
163188
164189 def _cmd_http (self , cmd ):
165190 try :
0 commit comments