terminate tasks gracefully and not forcefully on closing VSCode or when using the "kill" (trashcan) button
Does this issue occur when all extensions are disabled?: Yes
- VS Code Version: 1.87.0 (and all versions before I can remember)
- OS Version: Ubuntu 22.04.4
Steps to Reproduce:
I am not able to create a real minimal example, but will show my exact usecase here and try to explain it.
- create a task with the command
bench startfrom frappe bench (https://github.com/frappe/bench) and run it- this starts 3 redis servers, a node server, a yarn watcher and some other stuff
- use the "kill" button for the task or close VSCode
bench startgot terminated, but all the processes it itself spawned are still running- reopening VSCode and starting the task again will error out, because the still running redis servers are blocking some necessary ports
- even if it would work, we would still have multiple resource hogging processes lingering in the background
Pressing CTRL-C instead in the tasks terminal gracefully shuts it down and bench start is able to do its proper teardown of all the spawned processes. I am not invested at all in bench so can't answer specific questions to it, but I know that it is using honcho and a Procfile to managing all these processes.
So I guess all I am asking for is a way for tasks to not be forcefully killed, but do the same as CTRL-C in the console would do to it.
This seems to describe that the same functionality already exists for launch.json: https://github.com/microsoft/vscode-js-debug/issues/630#issuecomment-732414805
This issue here is similar to mine but only concerned about the kill button, and not closing VSCode. https://github.com/microsoft/vscode/issues/160740
This feature request is now a candidate for our backlog. The community has 60 days to upvote the issue. If it receives 20 upvotes we will move it to our backlog. If not, we will close it. To learn more about how we handle feature requests, please see our documentation.
Happy Coding!
I agree with this. I guess terminate task using SIGKILL which can't be trapped. I need execute some commands to clean the tmp files created by this task
:slightly_smiling_face: This feature request received a sufficient number of community upvotes and we moved it to our backlog. To learn more about how we handle feature requests, please see our documentation.
Happy Coding!
Great, I am really glad that it reached the backlog!
If I may make a recommendation:
- I think the current way should stay as the default way to always be backwards compatible.
- What I and others want here should be an optional and explicit setting for a task.
This is especially useful for long running tasks - I've ran across it while creating a task that requires specific ports and runs a clean up process on SIGINT (eg: Firebase Emulator).
If I stopped the task by clicking trash icon, I found that the process had continued in the background, which meant the required ports were still in use and had to be killed individually using lsof -I :$PORT_NUMBER to identify the ID of the underlying Java process, then kill $PID. Doing that for 9 separate ports every time you need to restart the emulator is less than ideal. π¬
Totally agree with @Mutantpenguin - this should be an explicit setting defined on a task by task basis.
Please make an option for this to work with SIGBREAK. I need to terminate our build tools, which have SIGBREAK handlers (just like Ctrl-C in the command prompt) clean up the build and write out partially built data. It's been a PITA for me since Terminate just kills the process.
Hi VSCode team. Is there any updates about this issue? I also met this issue in our VSCode extension.
This has been an issue for me for the last few months using VS Code, not sure exactly what version it started, but after updating today it got even worse. I'm developing on Windows with NodeJS (Express backend, Angular frontend, running as tasks within VS Code), every time I close the window, close the workspace, kill tasks or restart running tasks it does not free the port (previous to today's update, this only occurred if I closed the window). If I gracefully kill the tasks within the terminal windows manually (Ctrl+C for my Express backend server, q+enter in the ng serve frontend server), everything works fine.
I've been blindly killing Node processes within Task Manager when this happens, but after today's update I got annoyed and wrote a little PowerShell script (and an accompanying VS Code task!) to automate this process. Hopefully this is resolved eventually, but until then here's the script/task I'm using:
PowerShell Script:
Param(
[int] $PortNumber,
[ValidateSet("TCP", "UDP", IgnoreCase = $true)]
[string] $Protocol = "TCP"
)
$Protocol = $Protocol.ToUpper()
$processId = $null
if ($Protocol -eq "TCP") {
try {
$connections = Get-NetTCPConnection -LocalPort $PortNumber -ErrorAction SilentlyContinue
if ($connections -is [System.Collections.IEnumerable]) {
$processId = $connections[0].OwningProcess
}
else {
$processId = $connections.OwningProcess
}
}
catch {
# Ignore error if no process is using the port
}
}
elseif ($Protocol -eq "UDP") {
try {
$connections = Get-NetUDPEndpoint -LocalPort $PortNumber -ErrorAction SilentlyContinue
if ($connections -is [System.Collections.IEnumerable]) {
$processId = $connections[0].OwningProcess
}
else {
$processId = $connections.OwningProcess
}
}
catch {
# Ignore error if no process is using the port
}
}
if ($null -eq $processId) {
Write-Host "No process is using $Protocol port $PortNumber"
return
}
$process = Get-Process -Id $processId
Write-Host "Killing $($process.ProcessName) process (PID: ${processId}) using ${Protocol} port ${PortNumber}..."
taskkill /F /PID $processId
And then you can run this easily within VS Code by creating a task. This task assumes the above script is saved as Stop-ProcessUsingPort.ps1 saved in C:\temp, but you can adjust the properties as needed
{
"version": "2.0.0",
"tasks": [
// Other tasks...
{
"label": "free-port",
"detail": "Free up a port that is currently in use.",
"type": "shell",
"command": "./Stop-ProcessUsingPort.ps1 -Protocol ${input:protocol} -PortNumber ${input:portNumber}",
"options": {
"cwd": "C:\\temp"
},
"problemMatcher": [],
"presentation": {
"close": false
},
"icon": {
"id": "debug-disconnect",
"color": "terminal.ansiRed"
}
}
],
"inputs": [
// Other inputs...
{
"id": "protocol",
"type": "pickString",
"description": "Select the protocol the port is using",
"default": "TCP",
"options": [
{
"value": "TCP",
"label": "Transmission Control Protocol"
},
{
"value": "UDP",
"label": "User Datagram Protocol"
}
]
},
{
"id": "portNumber",
"type": "promptString",
"description": "Enter the port number to free",
"default": "3002"
}
]
}
I'm thinking this opt-in setting should apply not only to tasks, but also terminals.
I initially added a setting to change the signal sent when killing terminals, but after further discussion, we believe this isn't the right long-term approach. Terminal processes are expected to handle SIGHUP appropriately, whether that means exiting cleanly or ignoring it. Automatically replacing SIGHUP with SIGTERM shifts that responsibility away from the process and may lead to unintended side effects. As a result, Iβm reverting this change. Instead, weβre considering exposing a command that would allow users to send specific signals (like SIGTERM) manually, https://github.com/microsoft/vscode/issues/250669.
The command would enable creating a keybinding to do this and an extension could add a button.
I am really sorry to hear about the revert and the proposed alternative solution. π
This might solve the problem of closing a terminal manually (not really sure since the existing button would have to be replaced?), but would not solve correct handling of terminals when closing VSCode.
I also don't understand Automatically replacing SIGHUP with SIGTERM as the new functionality was opt in.
but would not solve correct handling of terminals when closing VSCode.
@Mutantpenguin the main thing I took from this when we looked into this yesterday was SIGHUP is literally the only correct handling of this. If you have something sticking around afterwards, it's because that's how the application behaves intentionally (like a daemon), and you should use the regular methods to handle that. If we offered this setting, I 100% foresee people complaining that the terminal is closing their long running daemon, leading to more support work for us.
So the solution is instead of making this niche (and arguably wrong) use case a core feature, provide a simple primitive to allow users to do this if they so choose.
Currently a work in progress but there will be this command:
Which you can keybind:
{
"key": "ctrl+alt+c",
"command": "workbench.action.terminal.sendSignal",
"args": { "signal": "SIGTERM" },
"when": "terminalFocus"
}
And an extension could then easily leverage that command to create a button near the terminal.
Part of managing an open source project is knowing when to say no, and this is one of those cases as this feature would be harmful due to added complexity in core kill logic, bloat on the user side, additional work on our team to support the inevitable complaints, etc.
Just a quick suggestion: what if a new option terminationSignal is added to individual task in tasks.json? So when the trashcan icon is clicked or "Tasks: Terminate Task" is used in command palette β VS Code would send that signal instead. VS Code could also force terminate after X seconds.
@Mutantpenguin will that resolve your issue?
We want the trash can icon to work as it does in all other terminals and send SIGHUP. You can assign a keybinding or add a button via an extension as described above to achieve what you're hoping for.