Skip to content

Xtyll/return on first response #100

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions pygdbmi/IoManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def get_gdb_response(
self,
timeout_sec: float = DEFAULT_GDB_TIMEOUT_SEC,
raise_error_on_timeout: bool = True,
return_on_first_response: bool = False,
) -> List[Dict]:
"""Get response from GDB, and block while doing so. If GDB does not have any response ready to be read
by timeout_sec, an exception is raised.
Expand All @@ -96,9 +97,9 @@ def get_gdb_response(
timeout_sec = 0

if USING_WINDOWS:
retval = self._get_responses_windows(timeout_sec)
retval = self._get_responses_windows(timeout_sec, return_on_first_response)
else:
retval = self._get_responses_unix(timeout_sec)
retval = self._get_responses_unix(timeout_sec, return_on_first_response)

if not retval and raise_error_on_timeout:
raise GdbTimeoutError(
Expand All @@ -108,7 +109,9 @@ def get_gdb_response(
else:
return retval

def _get_responses_windows(self, timeout_sec: float) -> List[Dict]:
def _get_responses_windows(
self, timeout_sec: float, return_on_first_response: bool
) -> List[Dict]:
"""Get responses on windows. Assume no support for select and use a while loop."""
timeout_time_sec = time.time() + timeout_sec
responses = []
Expand All @@ -132,6 +135,8 @@ def _get_responses_windows(self, timeout_sec: float) -> List[Dict]:
responses += responses_list
if timeout_sec == 0:
break
elif return_on_first_response is True and responses:
break
elif responses_list and self._allow_overwrite_timeout_times:
timeout_time_sec = min(
time.time() + self.time_to_check_for_additional_output_sec,
Expand All @@ -142,7 +147,9 @@ def _get_responses_windows(self, timeout_sec: float) -> List[Dict]:

return responses

def _get_responses_unix(self, timeout_sec: float) -> List[Dict]:
def _get_responses_unix(
self, timeout_sec: float, return_on_first_response: bool
) -> List[Dict]:
"""Get responses on unix-like system. Use select to wait for output."""
timeout_time_sec = time.time() + timeout_sec
responses = []
Expand Down Expand Up @@ -174,7 +181,8 @@ def _get_responses_unix(self, timeout_sec: float) -> List[Dict]:

if timeout_sec == 0: # just exit immediately
break

elif return_on_first_response is True and responses:
break
elif responses_list and self._allow_overwrite_timeout_times:
# update timeout time to potentially be closer to now to avoid lengthy wait times when nothing is being output by gdb
timeout_time_sec = min(
Expand All @@ -197,7 +205,10 @@ def _get_responses_list(
"""
responses: List[Dict[Any, Any]] = []

(_new_output, self._incomplete_output[stream],) = _buffer_incomplete_responses(
(
_new_output,
self._incomplete_output[stream],
) = _buffer_incomplete_responses(
raw_output, self._incomplete_output.get(stream)
)

Expand Down Expand Up @@ -228,6 +239,7 @@ def write(
timeout_sec: float = DEFAULT_GDB_TIMEOUT_SEC,
raise_error_on_timeout: bool = True,
read_response: bool = True,
return_on_first_response: bool = False,
) -> List[Dict]:
"""Write to gdb process. Block while parsing responses from gdb for a maximum of timeout_sec.

Expand Down Expand Up @@ -282,7 +294,9 @@ def write(

if read_response is True:
return self.get_gdb_response(
timeout_sec=timeout_sec, raise_error_on_timeout=raise_error_on_timeout
timeout_sec=timeout_sec,
raise_error_on_timeout=raise_error_on_timeout,
return_on_first_response=return_on_first_response,
)

else:
Expand Down
12 changes: 10 additions & 2 deletions pygdbmi/gdbcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,28 @@ def get_gdb_response(
self,
timeout_sec: float = DEFAULT_GDB_TIMEOUT_SEC,
raise_error_on_timeout: bool = True,
return_on_first_response: bool = False,
) -> List[Dict]:
"""Get gdb response. See IoManager.get_gdb_response() for details"""
return self.io_manager.get_gdb_response(timeout_sec, raise_error_on_timeout)
return self.io_manager.get_gdb_response(
timeout_sec, raise_error_on_timeout, return_on_first_response
)

def write(
self,
mi_cmd_to_write: Union[str, List[str]],
timeout_sec: float = DEFAULT_GDB_TIMEOUT_SEC,
raise_error_on_timeout: bool = True,
read_response: bool = True,
return_on_first_response: bool = False,
) -> List[Dict]:
"""Write command to gdb. See IoManager.write() for details"""
return self.io_manager.write(
mi_cmd_to_write, timeout_sec, raise_error_on_timeout, read_response
mi_cmd_to_write=mi_cmd_to_write,
timeout_sec=timeout_sec,
raise_error_on_timeout=raise_error_on_timeout,
read_response=read_response,
return_on_first_response=return_on_first_response,
)

def exit(self) -> None:
Expand Down
21 changes: 21 additions & 0 deletions tests/test_gdbcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import random
import shutil
import subprocess
import time

import pytest

Expand Down Expand Up @@ -97,6 +98,26 @@ def test_controller() -> None:
responses = gdbmi.write(["-break-insert main", "-exec-run"])


def test_return_on_first_response() -> None:
gdbmi = GdbController(time_to_check_for_additional_output_sec=0)
c_hello_world_binary = _get_c_program("hello", "pygdbmiapp.a")

if USING_WINDOWS:
c_hello_world_binary = c_hello_world_binary.replace("\\", "/")
# Load the binary and its symbols in the gdb subprocess
responses = gdbmi.write(
"-file-exec-and-symbols %s" % c_hello_world_binary, timeout_sec=1
)
responses = gdbmi.write(
"-file-exec-and-symbols %s" % c_hello_world_binary, timeout_sec=1
)
timeout_sec = 10.0
start_time = time.time()
responses = gdbmi.write("stepi", timeout_sec=timeout_sec, return_on_first_response=True)
endtime = time.time()
assert(start_time + timeout_sec > endtime)


@pytest.mark.skip()
def test_controller_buffer_randomized() -> None:
"""
Expand Down