Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IoManager._get_responses_windows mangles token when reading from stdout #54

Open
leonardopsantos opened this issue May 18, 2021 · 0 comments · May be fixed by #76
Open

IoManager._get_responses_windows mangles token when reading from stdout #54

leonardopsantos opened this issue May 18, 2021 · 0 comments · May be fixed by #76

Comments

@leonardopsantos
Copy link

leonardopsantos commented May 18, 2021

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
@leonardopsantos leonardopsantos changed the title IoManager._get_responses_windows mangles token when reading form stdout IoManager._get_responses_windows mangles token when reading from stdout May 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant