-
Notifications
You must be signed in to change notification settings - Fork 48
Description
Describe the bug
The IoManager._get_responses_windows()
method sometimes doesn't read the MI token.
To Reproduce
I'm using pygdbmi to drive arm-none-eabi-gdb
. I'm issuing commands using a token:
0-gdb-set trace-commands on
1-gdb-set logging on
And so forth. The reply from GDB is
0^done
1^done
The problem is that when issuing the command 2-gdb-set print repeats 0
, GDB replies with 2^done
, but IoManager._get_responses_windows()
only reads ^done
. As I'm using the tokens to match the commands with the replies, my SW fails.
To really check that it's a problem with pygdbmi, I tried to directly call arm-none-eabi-gdb
with the following script:
gdb_args = [arm-none-eabi-gdb]
gdb_args.append('--init-command=.gdbinit')
gdb_args.append('--quiet')
gdb_args.append('--interpreter=mi3')
with open('gdb_stdout.txt', 'w') as f_out:
gdb_process = subprocess.Popen(
gdb_args,
shell=False,
stdout=f_out,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
bufsize=0,
)
gdb_process.stdin.write('0-gdb-set trace-commands on\n'.encode())
time.sleep(0.5)
gdb_process.stdin.write('1-gdb-set logging on\n'.encode())
time.sleep(0.5)
gdb_process.stdin.write('2-gdb-set print repeats 0\n'.encode())
time.sleep(0.5)
gdb_process.stdin.write('3-gdb-set print elements 0\n'.encode())
time.sleep(0.5)
The gdb_stdout.txt
file is
(gdb)
~"+set trace-commands on\n"
0^done
(gdb)
~"+set logging on\n"
~"Already logging to gdb.txt.\n"
1^done
(gdb)
~"+set print repeats 0\n"
2^done
(gdb)
~"+set print elements 0\n"
3^done
(gdb)
~"Exception condition detected on fd 0\n"
~"error detected on stdin\n"
So, clearly, GDB is indeed replying 2^done
I've enabled debugging in IOManager
with and also added some more debug statements:
logging.basicConfig(filename='example.log', level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
def _get_responses_windows(self, timeout_sec):
"""Get responses on windows. Assume no support for select and use a while loop."""
timeout_time_sec = time.time() + timeout_sec
responses = []
while True:
responses_list = []
try:
self.stdout.flush()
raw_output = self.stdout.readline().replace(b"\r", b"\n")
logger.debug("raw stdout {}".format(repr(raw_output)))
responses_list = self._get_responses_list(raw_output, "stdout")
except IOError:
pass
try:
self.stderr.flush()
raw_output = self.stderr.readline().replace(b"\r", b"\n")
logger.debug("raw stderr {}".format(repr(raw_output)))
responses_list += self._get_responses_list(raw_output, "stderr")
except IOError:
pass
And got:
DEBUG:pygdbmi.IoManager:writing: 2-gdb-set print repeats 0
DEBUG:pygdbmi.IoManager:raw stdout b'"+set print repeats 0\\n"\n\n'
DEBUG:pygdbmi.IoManager:{'message': None,
'payload': '"+set print repeats 0\\n"',
'stream': 'stdout',
'type': 'output'}
DEBUG:pygdbmi.IoManager:raw stdout b'^done\n\n'
DEBUG:pygdbmi.IoManager:{'message': 'done',
'payload': None,
'stream': 'stdout',
'token': None,
'type': 'result'}
Looking at the gdb log, it's definitively printing the token:
~"+set print repeats 0\n"
2^done
(gdb)
Please complete the following information:
- OS: Windows 10 64 bits
- pygdbmi version (
pip freeze
output): 0.10.0.0