diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java
index 3e74cd449221..a950e4153e0a 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalTtyConnector.java
@@ -1,15 +1,19 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.terminal;
+import com.google.common.base.Ascii;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.terminal.pty.PtyProcessTtyConnector;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.jediterm.core.util.TermSize;
import com.pty4j.PtyProcess;
import com.pty4j.unix.UnixPtyProcess;
+import com.pty4j.windows.conpty.WinConPtyProcess;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import java.io.IOException;
+import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
@@ -35,10 +39,35 @@ public class LocalTerminalTtyConnector extends PtyProcessTtyConnector {
}, 1000, TimeUnit.MILLISECONDS);
}
else {
+ if (myProcess instanceof WinConPtyProcess winConPtyProcess && !winConPtyProcess.isBundledConPtyLibrary()) {
+ sendInterruptToWinConPtyProcess();
+ }
myProcess.destroy();
}
}
+ /**
+ * Workaround for the ConPTY issue #15373
+ * which was fixed in Windows Terminal 1.22.
+ * Even though this version is bundled with IDE, ConPTY can be loaded from the OS.
+ * @see workaround discussion
+ */
+ private void sendInterruptToWinConPtyProcess() {
+ OutputStream outputStream = myProcess.getOutputStream();
+ if (outputStream != null && myProcess.isAlive()) {
+ try {
+ // ConPTY will process `0x03` and raise `CTRL_C_EVENT`.
+ // This will hopefully terminate the whole process hierarchy of running user command,
+ // which is a must for commands like `npm run dev`.
+ outputStream.write(Ascii.ETX);
+ outputStream.flush();
+ }
+ catch (IOException e) {
+ LOG.info("Failed to send Ctrl+C to " + myProcess.getClass().getSimpleName() + ", alive:" + myProcess.isAlive(), e);
+ }
+ }
+ }
+
@Override
public void resize(@NotNull TermSize termSize) {
if (LOG.isDebugEnabled()) {