-
-
Notifications
You must be signed in to change notification settings - Fork 602
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
Add timeouts for commit hooks #2547
base: master
Are you sure you want to change the base?
Conversation
Opening early as a draft. Initial changes are working and have tests added for them just need to figure out how we are going to implement a timeout value, if thats user configuration or a default impl. |
Was wanting to get some feedback on this before progressing further, is this the correct place to implement the timeout logic? @extrawurst |
This would impact other users like Gitbutler. @Byron what do you think about this change? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From an implementation standpoint, this looks good. The only thing I would add is tests for non-zero timeouts (maybe that’s something you already planned or maybe I missed something).
Also worth mentioning as its done in this PR, I've changed the test shell shebang to use |
I've also noticed that while running tests that since i use the non POSIX Shell (nushell) that i need to prefix the command with SHELL=bash, i was wondering if it may be worth testing if the $SHELL is a known non compliant shell and trying to look for a default POSIX shell in the path? |
Now that the implementation is solid how do i go about with setting the timeout, how do we expose configurable value for the user and should there be a default timeout? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for letting me know, @extrawurst.
The changes seem to not apply to git2-hooks
, so wouldn't affect GitButler in its current form. However, that would change if timeouts would move into git2-hooks
as I seem to be proposing :).
PS: I unsubscribed as this PR is relevant to me only once git2-hooks
is involved. You can always ping me to change that.
…meouts All hooks functions now have their own with_timeout variant inside git2-hooks and asyncgit. The previous implementation of using a new thread with a timeout has been ditched in favour of a child command which we can now poll and kill to prevent the hook from continueing. I've added a hard coded default 5 second timeout but this will be handled by the Options struct later
@Byron I've updated the implementation and it is now inside git2-hooks, I've added new functions with suffixed |
The last remaining thing to do is move the tests i had written over to the git2_hooks crate, even so the current tests in asyncgit should be able to cover most cases i think. |
I was also thinking about the initial issue where the problem was an infinite wait because the hook was waiting for input, maybe a solution could be when a hook is running a new window is shown with the stdio from the hook and also allowing stdin, not sure if that would work how im thinking though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the quick turnaround!
The new implementation definitely addresses the previous issue, and now the timeout has an actual effect on the hook.
When looking at git2-hooks
exclusively, I am not sure I saw a test for this though.
@@ -130,7 +136,28 @@ impl HookPaths { | |||
"DUMMY_ENV_TO_FIX_WINDOWS_CMD_RUNS", | |||
"FixPathHandlingOnWindows", | |||
) | |||
.output()?; | |||
.stdout(Stdio::piped()) | |||
.stderr(Stdio::piped()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the semantics we had before, where stdin
was null (see the docs of output
).
Doing so should also make it impossible for a hook to hang waiting on stdin
. Hooks which still hang are probably buggy in another way.
} | ||
|
||
std::thread::yield_now(); | ||
std::thread::sleep(Duration::from_millis(10)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't sleep()
imply a yield, among other things?
@@ -66,6 +67,10 @@ pub enum HookResult { | |||
/// path of the hook that was run | |||
hook: PathBuf, | |||
}, | |||
TimedOut { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs are missing.
Probably the crate could use a deny(missing_docs)
as well.
@@ -106,7 +108,11 @@ impl HookPaths { | |||
|
|||
/// this function calls hook scripts based on conventions documented here | |||
/// see <https://git-scm.com/docs/githooks> | |||
pub fn run_hook(&self, args: &[&str]) -> Result<HookResult> { | |||
pub fn run_hook( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this doesn't have to be a breaking change unless one really wants to tell folks to deal with the timeout. That timeouts are implemented now probably means most people didn't have issues with this (or solved them by fixing the hooks), so I'd argue that run_hook_with_timeout()
should be favored.
} | ||
|
||
std::thread::yield_now(); | ||
std::thread::sleep(Duration::from_millis(10)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One could think about a quadratic backoff (or a custom sequence) here where the first few milliseconds are checked more often, and as it takes longer, one checks less often.
This might also be overthinking it as 10ms seems fine.
Depending on how this is done, I think one should mention in the docs that the timeout
may prolong the actual runtimes, right now by up to 10ms.
@@ -106,7 +108,11 @@ impl HookPaths { | |||
|
|||
/// this function calls hook scripts based on conventions documented here | |||
/// see <https://git-scm.com/docs/githooks> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a documentation update.
This Pull Request closes #2546.
It changes the following:
I followed the checklist:
make check
without errors