mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
cli: fix attach does not always work (#181273)
* fix: don't sync debug.lastExtensionDevelopmentWorkspace * cli: fix attach does not always work Seems like reading stdin when it's open but never written to blocks the process. Fix that, both by checking IS_INTERACTIVE_CLI before reading stdin, and by not passing stdin to the tunnel subprocess. Fixes #179122
This commit is contained in:
parent
e78d4b7478
commit
cda21c19a7
|
@ -63,29 +63,31 @@ pub async fn start_singleton_client(args: SingletonClientArgs) -> bool {
|
|||
"An existing tunnel is running on this machine, connecting to it..."
|
||||
);
|
||||
|
||||
let stdin_handle = rpc.get_caller(msg_tx.clone());
|
||||
thread::spawn(move || {
|
||||
let mut input = String::new();
|
||||
loop {
|
||||
input.truncate(0);
|
||||
if *IS_INTERACTIVE_CLI {
|
||||
let stdin_handle = rpc.get_caller(msg_tx.clone());
|
||||
thread::spawn(move || {
|
||||
let mut input = String::new();
|
||||
loop {
|
||||
input.truncate(0);
|
||||
println!("reading line");
|
||||
match std::io::stdin().read_line(&mut input) {
|
||||
Err(_) | Ok(0) => return, // EOF or not a tty
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match std::io::stdin().read_line(&mut input) {
|
||||
Err(_) | Ok(0) => return, // EOF or not a tty
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match input.chars().next().map(|c| c.to_ascii_lowercase()) {
|
||||
Some('x') => {
|
||||
stdin_handle.notify(protocol::singleton::METHOD_SHUTDOWN, EmptyObject {});
|
||||
return;
|
||||
match input.chars().next().map(|c| c.to_ascii_lowercase()) {
|
||||
Some('x') => {
|
||||
stdin_handle.notify(protocol::singleton::METHOD_SHUTDOWN, EmptyObject {});
|
||||
return;
|
||||
}
|
||||
Some('r') => {
|
||||
stdin_handle.notify(protocol::singleton::METHOD_RESTART, EmptyObject {});
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
Some('r') => {
|
||||
stdin_handle.notify(protocol::singleton::METHOD_RESTART, EmptyObject {});
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let caller = rpc.get_caller(msg_tx);
|
||||
let mut rpc = rpc.methods(SingletonServerContext {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ChildProcess, ChildProcessWithoutNullStreams, spawn, SpawnOptions } from 'child_process';
|
||||
import { ChildProcess, spawn, SpawnOptions, StdioOptions } from 'child_process';
|
||||
import { chmodSync, existsSync, readFileSync, statSync, truncateSync, unlinkSync } from 'fs';
|
||||
import { homedir, release, tmpdir } from 'os';
|
||||
import type { ProfilingSession, Target } from 'v8-inspect-profiler';
|
||||
|
@ -56,20 +56,21 @@ export async function main(argv: string[]): Promise<any> {
|
|||
}
|
||||
const tunnelArgs = argv.slice(argv.indexOf('tunnel') + 1); // all arguments behind `tunnel`
|
||||
return new Promise((resolve, reject) => {
|
||||
let tunnelProcess: ChildProcessWithoutNullStreams;
|
||||
let tunnelProcess: ChildProcess;
|
||||
const stdio: StdioOptions = ['ignore', 'pipe', 'pipe'];
|
||||
if (process.env['VSCODE_DEV']) {
|
||||
tunnelProcess = spawn('cargo', ['run', '--', 'tunnel', ...tunnelArgs], { cwd: join(getAppRoot(), 'cli') });
|
||||
tunnelProcess = spawn('cargo', ['run', '--', 'tunnel', ...tunnelArgs], { cwd: join(getAppRoot(), 'cli'), stdio });
|
||||
} else {
|
||||
const appPath = process.platform === 'darwin'
|
||||
// ./Contents/MacOS/Electron => ./Contents/Resources/app/bin/code-tunnel-insiders
|
||||
? join(dirname(dirname(process.execPath)), 'Resources', 'app')
|
||||
: dirname(process.execPath);
|
||||
const tunnelCommand = join(appPath, 'bin', `${product.tunnelApplicationName}${isWindows ? '.exe' : ''}`);
|
||||
tunnelProcess = spawn(tunnelCommand, ['tunnel', ...tunnelArgs], { cwd: cwd() });
|
||||
tunnelProcess = spawn(tunnelCommand, ['tunnel', ...tunnelArgs], { cwd: cwd(), stdio });
|
||||
}
|
||||
|
||||
tunnelProcess.stdout.pipe(process.stdout);
|
||||
tunnelProcess.stderr.pipe(process.stderr);
|
||||
tunnelProcess.stdout!.pipe(process.stdout);
|
||||
tunnelProcess.stderr!.pipe(process.stderr);
|
||||
tunnelProcess.on('exit', resolve);
|
||||
tunnelProcess.on('error', reject);
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import { INativeEnvironmentService } from 'vs/platform/environment/common/enviro
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILogger, ILoggerService, LogLevelToString } from 'vs/platform/log/common/log';
|
||||
import { dirname, join } from 'vs/base/common/path';
|
||||
import { ChildProcess, spawn } from 'child_process';
|
||||
import { ChildProcess, StdioOptions, spawn } from 'child_process';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { CancelablePromise, createCancelablePromise, Delayer } from 'vs/base/common/async';
|
||||
|
@ -322,6 +322,8 @@ export class RemoteTunnelService extends Disposable implements IRemoteTunnelServ
|
|||
resolve(-1);
|
||||
}
|
||||
let tunnelProcess: ChildProcess | undefined;
|
||||
const stdio: StdioOptions = ['ignore', 'pipe', 'pipe'];
|
||||
|
||||
token.onCancellationRequested(() => {
|
||||
if (tunnelProcess) {
|
||||
this._logger.info(`${logLabel} terminating(${tunnelProcess.pid})`);
|
||||
|
@ -331,12 +333,12 @@ export class RemoteTunnelService extends Disposable implements IRemoteTunnelServ
|
|||
if (!this.environmentService.isBuilt) {
|
||||
onOutput('Building tunnel CLI from sources and run', false);
|
||||
onOutput(`${logLabel} Spawning: cargo run -- tunnel ${commandArgs.join(' ')}`, false);
|
||||
tunnelProcess = spawn('cargo', ['run', '--', 'tunnel', ...commandArgs], { cwd: join(this.environmentService.appRoot, 'cli') });
|
||||
tunnelProcess = spawn('cargo', ['run', '--', 'tunnel', ...commandArgs], { cwd: join(this.environmentService.appRoot, 'cli'), stdio });
|
||||
} else {
|
||||
onOutput('Running tunnel CLI', false);
|
||||
const tunnelCommand = this.getTunnelCommandLocation();
|
||||
onOutput(`${logLabel} Spawning: ${tunnelCommand} tunnel ${commandArgs.join(' ')}`, false);
|
||||
tunnelProcess = spawn(tunnelCommand, ['tunnel', ...commandArgs], { cwd: homedir() });
|
||||
tunnelProcess = spawn(tunnelCommand, ['tunnel', ...commandArgs], { cwd: homedir(), stdio });
|
||||
}
|
||||
|
||||
tunnelProcess.stdout!.on('data', data => {
|
||||
|
|
Loading…
Reference in a new issue