-
Notifications
You must be signed in to change notification settings - Fork 30k
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
Make _activeTasks synchronous wrt _executeTask #180617
Conversation
5413180
to
39a1a6c
Compare
edde211
to
a473d38
Compare
This still isn't right. This version once again reports false dependency cycles. I'm working on a fix. |
Fixes microsoft#180578 The problem was that after a call to _executeTask there is a delay (at least until the next tick, but potentially considerably longer) before the task is added to _activeTasks. During this period a second instance of the task could be kicked off, causing problems. This commit fixes the issue by adding an entry (without a terminal) to _activeTasks before returning from _executeTask. For the most part though, it preserves the existing behavior - so for example `getActiveTasks` only returns the tasks that have terminals attached, just as it did before; and there is no change to when `TaskEvent` events are fired for the task.
The way dependency cycles were detected no longer works now that activeTasks is populated early. Fix it.
8b4ca12
to
fda6f9c
Compare
Sorry for the churn. This version fixes both issues:
|
Thanks so much for looking into this. We have endgame this week, so i'll test your PRs after that. |
Fixes microsoft#180850 If a task appears multiple times within a dependency hierarchy, it will usually still be running for each subsequent visit, and won't be launched again. But if it finishes before the next instance is visited, it will be run a second time. This can easily happen if a parent task's `dependsOrder` is set to `"sequence"`. This fixes the problem by keeping track of the promises associated with all the tasks that have been started so far.
I just added a commit that fixes #180850 - but I can't see a way to link this pull request to that issue... |
This works well, thank you! |
4cfa4f8
to
08929a2
Compare
da9676e
to
ff7d86a
Compare
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 change breaks 180850. I'm not allowed to request changes apparently...
@meganrogge you marked this as fixing #180243 - but it doesn't (it doesn't even address it). It does fix #180850 though. |
@markw65 it does fix that with this change |
@@ -294,7 +294,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { | |||
} | |||
const lastTaskInstance = this.getLastInstance(task); | |||
const terminalData = lastTaskInstance ? this._activeTasks[lastTaskInstance.getMapKey()] : undefined; | |||
if (terminalData && terminalData.promise && !validInstance) { | |||
if (terminalData && terminalData.promise && !validInstance && !task.configurationProperties.dependsOn?.length) { |
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 seems wrong? Now a task with dependencies can be run as many times as you like, regardless of its instanceLimit
.
There is another bug here, which is that a task with an instance limit can be launched as a dependent task without adding to its instance count, and then launched as a top level task, possibly exceeding its intstancelimit. The fix for that is to move the instance limit checking into _executeTask; and I started a diff to do that. But I wanted to let this settle first...
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.
Now a task with dependencies can be run as many times as you like, regardless of its instanceLimit.
When I tested, that was not the case.
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.
probably because the ones that are already in encounteredTasks are returned here and not rerun https://github.com/markw65/vscode/blob/0476301a02badbe7d3a4ba2aa96599c66960e4d6/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts#L552
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.
Well, it does. Try this with a current build:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"command": "echo dependent",
"label": "dependent",
"problemMatcher": []
},
{
"type": "shell",
"command": "echo Running top level task...;sleep 5;echo done",
"label": "toplevel",
"dependsOn": ["dependent"],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
}
]
}
Now hit Cmd-Shift-B a few times; each one will start a new task, rather than telling you the task is already running. It was already somewhat broken (#180541) before this commit; but without this specific change, this commit would have fixed #180541. Now its completely broken it...
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.
Also, sorry, I didn't get notified about your response until this morning for some reason...
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.
@markw65 In insider's, with these changes and that task, I cannot reproduce the issue you describe. I see a notification that the task is already active and am asked if i'd like to terminate or restart it.
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.
@meganrogge Are you sure its in the insiders you're testing with? In order to get that popup, run
has to return { kind: TaskExecuteKind.Active, ... }
, and after the change above, it can only do that if the task has no dependents. Tasks with dependents simply ignore their instanceLimit.
If I checkout d980921 (main after this was merged), and build, the problem above repros. If I remove the && !task.configurationProperties.dependsOn?.length
the problem goes away; and if I checkout main as of now, the problem has been fixed by #180546.
Ah - I missed that. |
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.
@meganrogge I'm not totally clear what's going on in this change, shall we talk through it tomorrow?
@@ -294,7 +294,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { | |||
} | |||
const lastTaskInstance = this.getLastInstance(task); | |||
const terminalData = lastTaskInstance ? this._activeTasks[lastTaskInstance.getMapKey()] : undefined; | |||
if (terminalData && terminalData.promise && !validInstance) { | |||
if (terminalData && terminalData.promise && !validInstance && !task.configurationProperties.dependsOn?.length) { |
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.
Now a task with dependencies can be run as many times as you like, regardless of its instanceLimit.
When I tested, that was not the case.
@@ -294,7 +294,7 @@ export class TerminalTaskSystem extends Disposable implements ITaskSystem { | |||
} | |||
const lastTaskInstance = this.getLastInstance(task); | |||
const terminalData = lastTaskInstance ? this._activeTasks[lastTaskInstance.getMapKey()] : undefined; | |||
if (terminalData && terminalData.promise && !validInstance) { | |||
if (terminalData && terminalData.promise && !validInstance && !task.configurationProperties.dependsOn?.length) { |
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.
probably because the ones that are already in encounteredTasks are returned here and not rerun https://github.com/markw65/vscode/blob/0476301a02badbe7d3a4ba2aa96599c66960e4d6/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts#L552
Fixes #180578
The problem was that after a call to _executeTask there is a delay (at least until the next tick, but potentially considerably longer) before the task is added to _activeTasks. During this period a second instance of the task could be kicked off, causing problems.
This commit fixes the issue by adding an entry (without a terminal) to _activeTasks before returning from _executeTask. For the most part though, it preserves the existing behavior - so for example
getActiveTasks
only returns the tasks that have terminals attached, just as it did before; and there is no change to whenTaskEvent
events are fired for the task.