-
-
Notifications
You must be signed in to change notification settings - Fork 906
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
Git.execute output_stream is not documented to suppress kill_after_timeout, but does #1762
Comments
Thanks for bringing this to my attention - I definitely wasn't aware. Generally, if the user obtains a running process, then they are responsible for handling it no auto-killing should happen. Thus I think the current behaviour, also in relation to Maybe we can consider to emit a warning if incompatible flags are specified to make people aware that their Maybe doing so then triggers new issues of users arguing for making this work, which is probably when it could be made to work. I am not quite sure what the wisest way of dealing with this is, as either change could be considered breaking, and documenting anything could make a 'breaking fix' impossible if the documentation endorses the status quo. I definitely lean to doing that though, but appreciate your advise and/or opinion on what to do here. |
Although passing Lines 1075 to 1082 in 4a9922f
When Line 1057 in 4a9922f
When Line 1082 in 4a9922f
Regarding whether that behavior should be considered correct, I think the docstring is intended to indicate specifically that behavior, but I am unsure: Lines 864 to 871 in 4a9922f
The reason I think it is intended to specify the current behavior is that, if the output were instead read in chunks and copied, allowing it to be used while the subprocess is still running, then that wouldn't generally be a reason not to use it. Either way, I think it would be a breaking change to make I think this doesn't necessarily mean
We can actually avoid creating the timer in any cases, because However, if this is to be done, then the idea of waiting for bigger design changes to add tests for With that said, if you're comfortable having such a change without an accompanying increase in test coverage, I'm fully willing to open a PR for it without changes to the tests. |
I see, thanks so much for taking the time to clarify with code-references. Admittedly I don't usually check the code if it's linked, and embedding it definitely assures I see it. In conjunction with the opportunity of using the new
Of course it would be great if the test-coverage could be improved when adding If you think there is enough coverage to make the change (maybe regardless some missing coverage), a PR would definitely be appreciated. It seems like the maintainability of the code would be improved with such change. PS: When seeing this it seems that Lines 1076 to 1078 in 4a9922f
|
That looks feasible. I'll try and look at it sometime soon. There are a few other GitPython-related things I've ended up being in the middle of at the same time (as each other), so I plan to finish--and/or or discover the unworkability of and abandon--a couple of those first, before circling back to try and make a PR for this. (But in saying this, it is not my intention to claim the issue. If, in the mean time, someone else comes along and fixes this, I certainly would not object.)
I'm not sure, but it does look like that could be a problem. I suspect that may not be natural o fix together with the above stuff, though. It might be better as its own issue. (I might be able to look into that and open one.) Or perhaps it will turn out easy to fix along with the rest of this. |
I am definitely glad that you are aware for a chance of a fix. What it tries to do is to stream Here is how the Rust implementation does it, similar to pub fn read2(p1: AnonPipe, v1: &mut Vec<u8>, p2: AnonPipe, v2: &mut Vec<u8>) -> io::Result<()> {
// Set both pipes into nonblocking mode as we're gonna be reading from both
// in the `select` loop below, and we wouldn't want one to block the other!
let p1 = p1.into_inner();
let p2 = p2.into_inner();
p1.set_nonblocking(true)?;
p2.set_nonblocking(true)?;
let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
fds[0].fd = p1.as_raw_fd();
fds[0].events = libc::POLLIN;
fds[1].fd = p2.as_raw_fd();
fds[1].events = libc::POLLIN;
loop {
// wait for either pipe to become readable using `poll`
cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;
if fds[0].revents != 0 && read(&p1, v1)? {
p2.set_nonblocking(false)?;
return p2.read_to_end(v2).map(drop);
}
if fds[1].revents != 0 && read(&p2, v2)? {
p1.set_nonblocking(false)?;
return p1.read_to_end(v1).map(drop);
}
}
// Read as much as we can from each pipe, ignoring EWOULDBLOCK or
// EAGAIN. If we hit EOF, then this will happen because the underlying
// reader will return Ok(0), in which case we'll see `Ok` ourselves. In
// this case we flip the other fd back into blocking mode and read
// whatever's leftover on that file descriptor.
fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
match fd.read_to_end(dst) {
Ok(_) => Ok(true),
Err(e) => {
if e.raw_os_error() == Some(libc::EWOULDBLOCK)
|| e.raw_os_error() == Some(libc::EAGAIN)
{
Ok(false)
} else {
Err(e)
}
}
}
}
} |
When calling
Git.execute
, including indirectly through the dynamic methods of aGit
object, passing a non-None
value ofoutput_stream
suppresses the effect ofkill_after_timeout
. Thethreading.Timer
object is created with the localkill_process
function as its callback, butstart
is never called on it.GitPython/git/cmd.py
Lines 1050 to 1079 in a58a6be
This situation appears not entirely intentional, because:
Timer
is created, even though it is never used.as_process
suppresseskill_after_timeout
(and thatas_process
suppressesoutput_stream
), does not mention any effect ofoutput_stream
onkill_after_timeout
.So either
kill_after_timeout
should be honored even whenoutput_stream
is used, or the docstring should be updated to mention that it does not (and the code possibly modified to not create theTimer
object in the case that it is unused).I am not sure which change should be made, so I'm opening this rather than a PR to propose one of them.
This is effectively separate from #1756. (One quality this shares with #1756 is that it is relevant only to the behavior of
Git.execute
and functions that use it. Functions that usehandle_process_output
are unaffected; itskill_after_timeout
is implemented differently with nonequivalent behavior and separate code.handle_process_output
also does not take anoutput_stream
argument.)The text was updated successfully, but these errors were encountered: