Browse Source

Fix sending SIGINT to the command process's subprocesses

Saoud Rizwan 1 year ago
parent
commit
15f52696b9
3 changed files with 20 additions and 1 deletions
  1. 9 0
      package-lock.json
  2. 1 0
      package.json
  3. 10 1
      src/ClaudeDev.ts

+ 9 - 0
package-lock.json

@@ -18,6 +18,7 @@
         "os-name": "^6.0.0",
         "os-name": "^6.0.0",
         "p-wait-for": "^5.0.2",
         "p-wait-for": "^5.0.2",
         "serialize-error": "^11.0.3",
         "serialize-error": "^11.0.3",
+        "tree-kill": "^1.2.2",
         "tree-sitter-wasms": "^0.1.11",
         "tree-sitter-wasms": "^0.1.11",
         "web-tree-sitter": "^0.22.6"
         "web-tree-sitter": "^0.22.6"
       },
       },
@@ -5616,6 +5617,14 @@
       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
       "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
       "license": "MIT"
       "license": "MIT"
     },
     },
+    "node_modules/tree-kill": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
+      "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
+      "bin": {
+        "tree-kill": "cli.js"
+      }
+    },
     "node_modules/tree-sitter-wasms": {
     "node_modules/tree-sitter-wasms": {
       "version": "0.1.11",
       "version": "0.1.11",
       "resolved": "https://registry.npmjs.org/tree-sitter-wasms/-/tree-sitter-wasms-0.1.11.tgz",
       "resolved": "https://registry.npmjs.org/tree-sitter-wasms/-/tree-sitter-wasms-0.1.11.tgz",

+ 1 - 0
package.json

@@ -131,6 +131,7 @@
     "os-name": "^6.0.0",
     "os-name": "^6.0.0",
     "p-wait-for": "^5.0.2",
     "p-wait-for": "^5.0.2",
     "serialize-error": "^11.0.3",
     "serialize-error": "^11.0.3",
+    "tree-kill": "^1.2.2",
     "tree-sitter-wasms": "^0.1.11",
     "tree-sitter-wasms": "^0.1.11",
     "web-tree-sitter": "^0.22.6"
     "web-tree-sitter": "^0.22.6"
   }
   }

+ 10 - 1
src/ClaudeDev.ts

@@ -16,6 +16,7 @@ import { DEFAULT_MAX_REQUESTS_PER_TASK } from "./shared/Constants"
 import { ClaudeAsk, ClaudeMessage, ClaudeSay, ClaudeSayTool } from "./shared/ExtensionMessage"
 import { ClaudeAsk, ClaudeMessage, ClaudeSay, ClaudeSayTool } from "./shared/ExtensionMessage"
 import { Tool, ToolName } from "./shared/Tool"
 import { Tool, ToolName } from "./shared/Tool"
 import { ClaudeAskResponse } from "./shared/WebviewMessage"
 import { ClaudeAskResponse } from "./shared/WebviewMessage"
+import treeKill from "tree-kill"
 
 
 const SYSTEM_PROMPT =
 const SYSTEM_PROMPT =
 	() => `You are Claude Dev, a highly skilled software developer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.
 	() => `You are Claude Dev, a highly skilled software developer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices.
@@ -627,7 +628,15 @@ export class ClaudeDev {
 							// if this ask promise is not ignored, that means the user responded to it somehow either by clicking primary button or by typing text
 							// if this ask promise is not ignored, that means the user responded to it somehow either by clicking primary button or by typing text
 							if (response === "yesButtonTapped") {
 							if (response === "yesButtonTapped") {
 								// SIGINT is typically what's sent when a user interrupts a process (like pressing Ctrl+C)
 								// SIGINT is typically what's sent when a user interrupts a process (like pressing Ctrl+C)
-								subprocess.kill("SIGINT") // will result in for loop throwing error
+								/*
+								.kill sends SIGINT by default. However by not passing any options into .kill(), execa internally sends a SIGKILL after a grace period if the SIGINT failed.
+								however it turns out that even this isn't enough for certain processes like npm starting servers. therefore we use the tree-kill package to kill all processes in the process tree, including the root process.
+								- Sends signal to all children processes of the process with pid pid, including pid. Signal defaults to SIGTERM.
+								*/
+								if (subprocess.pid) {
+									//subprocess.kill("SIGINT") // will result in for loop throwing error
+									treeKill(subprocess.pid, "SIGINT")
+								}
 							} else {
 							} else {
 								// if the user sent some input, we send it to the command stdin
 								// if the user sent some input, we send it to the command stdin
 								// add newline as cli programs expect a newline after each input
 								// add newline as cli programs expect a newline after each input