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

Cancellation for Executable #9522

Merged

Conversation

gerhardol
Copy link
Member

@gerhardol gerhardol commented Aug 19, 2021

Fixes #9440
#9440 is mostly closed in #9505, this handles a few effects
Closes #9501

Proposed changes

Long running process like "git difftool --tool-help" are currently never cancelled, they must run to exit.
I have seen this command require over a minute at work.
After #9505, there is no major problem due to this, it is possible to open the console and close GE quickly after opening, but it could be a potential issue.

  • CancellationToken for Executable
    Possibility to cancel processes, not hanging until closing.
    There may be other ways to do this too.

  • CancellationToken handling for CustomDiffMergeTools
    Runs in the background and was never cancelled before. This add cancellation token handling and also cancels the Git command.
    A few other cleanups, review commit by commit

Test methodology

Manual

  • Start Settings to clear the cache for merge/diff tools
  • F12 for command log
  • Open Solve merge conflicts... form
  • Notice mergetool --tool-help in the list
  • Close ResolveConflicts
  • Notice that the time is updated immediately, no exit code is written (before the command always ran to completion

Merge strategy

I agree that the maintainer squash merge this PR (if the commit message is clear).


✒️ I contribute this code under The Developer Certificate of Origin.

@ghost ghost assigned gerhardol Aug 19, 2021
GitCommands/CustomDiffMergeToolCache.cs Show resolved Hide resolved
GitCommands/CustomDiffMergeToolCache.cs Outdated Show resolved Hide resolved
GitUI/CommandsDialogs/FormBrowse.cs Outdated Show resolved Hide resolved
GitUI/CustomDiffMergeToolProvider.cs Outdated Show resolved Hide resolved
Plugins/GitUIPluginInterfaces/IProcess.cs Outdated Show resolved Hide resolved
@gerhardol
Copy link
Member Author

We need to kill the process when cancellation is requested

See #9522 (comment)

@RussKie RussKie added the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Aug 22, 2021
@ghost ghost removed the 📭 needs: author feedback More info/confirmation awaited from OP; issues typically get closed after 30 days of inactivity label Aug 22, 2021
@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch from 4a2a944 to cc16151 Compare August 22, 2021 08:48
@gerhardol
Copy link
Member Author

Minor review comments, rebased to add cancellation after #9524 was merged #9524 (review)

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 22, 2021
When forms starting list of custom diff/merge tools are closed,
cancel the handling including the Git process.

CustomMergeTools: Decrease delay before listing
@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch from cc16151 to be57392 Compare August 22, 2021 13:42
@gerhardol
Copy link
Member Author

Rebased and squashed and updated commit messages, rebase merge tomorrow

Renamed one more exitTask method
image

public Task WaitForExitAsync(CancellationToken token) => _process.WaitForExitAsync(token);

/// <inheritdoc />
public int WaitForExitTask()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name is confusing and wrong. It returns an int and not a task. The same goes for the async version.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method "waits for the exitTask" created when the process exits, including the extra work to add to log etc.
It is not a normal WaitForExit() that waits for the process task to exit.

I still think the name is better.
But what about WaitForProcessExit()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the non-async form of WaitForExitAsync so should be called WaitForExit in order to be consistent with the rest of the framework (e.g. Read/ReadAsync, Write/WriteAsycn, ...).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But there are two variants of WaitForExit() now: One that waits for the process to exit (that I added, cancellable) and the existing that waits for the additional exitTask to exit. I find the new method to follow the intention of the WaitForExit() method better, but I can rename that instead.

Copy link
Member

@RussKie RussKie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gerhardol
Copy link
Member Author

👍

Was that for calling the existing exitTask as WaitForProcessExit() or reverting to WaitForExit() and rename the new cancellable method (call that WaitForProcessExit() instead?`)?

Once on .NET 6.0 we will have this: https://devblogs.microsoft.com/dotnet/new-dotnet-6-apis-driven-by-the-developer-community/#waitasync-improvements

Unfortunately no change here, the additional exitTask is the problem here it seems.

@RussKie
Copy link
Member

RussKie commented Aug 25, 2021

It's almost a midnight here, and you're asking complex questions :D

/// </summary>
/// <param name="token">An optional token to cancel the asynchronous operation.</param>
/// <returns>A task that will complete when the process has exited, cancellation has been requested, or an error occurs.</returns>
Task WaitForExitAsync(CancellationToken token);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now we have:

/// Blocks the calling thread until the process exits, or when this object is disposed.
int WaitForProcessExit();

/// Returns a task that completes when the process exits, or when this object is disposed.
Task<int> WaitForProcessExitAsync();

/// Instructs the process component to wait for the associated process to exit, or for the cancellationToken to be cancelled (cancells the process).
Task WaitForExitAsync(CancellationToken token);

Maybe we can do something like this, and remove the need for the new method?

            public Task<int> WaitForProcessExitAsync(CancellationToken token)
            {
                token.Register(() => _exitTaskCompletionSource.SetCanceled(token));
                return _exitTaskCompletionSource.Task;
            }

Copy link
Member Author

@gerhardol gerhardol Aug 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really an option, exitTask is awaiten together with tasks for stdout and possibly stderr.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be an option, I do not get the cancellation working though.
Will be away from the compiler for a few days

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not get this working, just renaming

gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 29, 2021
When forms starting list of custom diff/merge tools are closed,
cancel the handling including the Git process.

CustomMergeTools: Decrease delay before listing
@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch 2 times, most recently from 2d3ea9d to 7dc2df2 Compare August 29, 2021 22:17
@gerhardol
Copy link
Member Author

gerhardol commented Aug 29, 2021

Rebased, renamed WaitForExitAsync back and the new cancellation method to WaitForProcessExitAsync (was not able to merge them, probable possible but lets settle with this).
Plan to squash tomorrow, merge one day later

@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch from 7dc2df2 to 7e998e3 Compare August 29, 2021 22:23
gerhardol added a commit to gerhardol/gitextensions that referenced this pull request Aug 30, 2021
When forms starting list of custom diff/merge tools are closed,
cancel the handling including the Git process.

CustomMergeTools: Decrease delay before listing
@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch from 7e998e3 to 6dd3a7d Compare August 30, 2021 19:57
@RussKie
Copy link
Member

RussKie commented Aug 31, 2021

We can iterate on this later, if necessary.

@gerhardol
Copy link
Member Author

gerhardol commented Aug 31, 2021

We can iterate on this later, if necessary.

I am considering setting the priority for the long running and Git "background" processes to BelowNormal
https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.priorityclass?view=net-5.0

Probably very little difference for users though

@RussKie
Copy link
Member

RussKie commented Aug 31, 2021 via email

@gerhardol
Copy link
Member Author

How do we tell whether a process is expected to be a long running one?

By knowledge, those we know may be long (currently these two in the PR).
In the same way GE could decrease prio for git --no-optional-locks and maybe no console visible.

But this fit in other PRs. I may look at this after the blame/filter PRs are merged

Cleanup: Remove unnecessary explicit throw if cancelled
When forms starting list of custom diff/merge tools are closed,
cancel the handling including the Git process.

CustomMergeTools: Decrease delay before listing
@gerhardol gerhardol force-pushed the feature/i9440-custom-difftools-token branch from 6dd3a7d to e71339c Compare August 31, 2021 19:44
@gerhardol gerhardol merged commit 7e33b66 into gitextensions:master Aug 31, 2021
@ghost ghost added this to the 3.6 milestone Aug 31, 2021
@gerhardol gerhardol deleted the feature/i9440-custom-difftools-token branch August 31, 2021 20:06
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 this pull request may close these issues.

[NBug] Value cannot be null.Parameter name: source Freeze after exiting from commit diff view
3 participants