From d233df9a12c187f64fe3295c80f4eda78581d51c Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 1 Feb 2018 14:22:12 -0800 Subject: [PATCH] Use named pipe for stdio in upload logs Fixes #42635 --- src/vs/code/electron-main/logUploader.ts | 10 ++++--- src/vs/code/electron-main/main.ts | 2 +- src/vs/code/node/cli.ts | 27 ++++++++++++++++++- .../environment/common/environment.ts | 1 + src/vs/platform/environment/node/argv.ts | 3 ++- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/vs/code/electron-main/logUploader.ts b/src/vs/code/electron-main/logUploader.ts index 6a05e9fd1bca8..dda702e0c2ff4 100644 --- a/src/vs/code/electron-main/logUploader.ts +++ b/src/vs/code/electron-main/logUploader.ts @@ -10,6 +10,7 @@ import * as cp from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import * as readline from 'readline'; +import * as net from 'net'; import { localize } from 'vs/nls'; import { ILaunchChannel } from 'vs/code/electron-main/launch'; @@ -17,6 +18,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import product from 'vs/platform/node/product'; import { IRequestService } from 'vs/platform/request/node/request'; import { IRequestContext } from 'vs/base/node/request'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; interface PostResult { readonly blob_id: string; @@ -35,7 +37,8 @@ class Endpoint { export async function uploadLogs( channel: ILaunchChannel, - requestService: IRequestService + requestService: IRequestService, + environmentService: IEnvironmentService ): TPromise { const endpoint = Endpoint.getFromProduct(); if (!endpoint) { @@ -45,7 +48,7 @@ export async function uploadLogs( const logsPath = await channel.call('get-logs-path', null); - if (await promptUserToConfirmLogUpload(logsPath)) { + if (await promptUserToConfirmLogUpload(logsPath, environmentService)) { console.log(localize('beginUploading', 'Uploading...')); const outZip = await zipLogs(logsPath); const result = await postLogs(endpoint, outZip, requestService); @@ -57,6 +60,7 @@ export async function uploadLogs( async function promptUserToConfirmLogUpload( logsPath: string, + environmentService: IEnvironmentService ): Promise { const message = localize('logUploadPromptHeader', 'Upload session logs to secure endpoint?') + '\n\n' + localize('logUploadPromptBody', 'Please review your log files here: \'{0}\'', logsPath) @@ -64,7 +68,7 @@ async function promptUserToConfirmLogUpload( + '\n\n' + localize('logUploadPromptKey', 'I have reviewed my logs (enter \'y\' to confirm upload)'); const rl = readline.createInterface({ - input: process.stdin, + input: net.connect(environmentService.args['upload-logs-stdin-pipe']), output: process.stdout }); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 8dd60aec8a2a8..6edfb099fdfb3 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -202,7 +202,7 @@ function setupIPC(accessor: ServicesAccessor): TPromise { // Log uploader if (environmentService.args['upload-logs']) { - return uploadLogs(channel, requestService) + return uploadLogs(channel, requestService, environmentService) .then(() => TPromise.wrapError(new ExpectedError())); } diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index ca0c7cdb8ab05..0fd0b2838354a 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -13,6 +13,7 @@ import pkg from 'vs/platform/node/package'; import * as paths from 'path'; import * as os from 'os'; import * as fs from 'fs'; +import * as net from 'net'; import { whenDeleted } from 'vs/base/node/pfs'; import { findFreePort } from 'vs/base/node/ports'; import { resolveTerminalEncoding } from 'vs/base/node/encoding'; @@ -312,7 +313,31 @@ export async function main(argv: string[]): TPromise { }; if (args['upload-logs']) { - options['stdio'] = [process.stdin, 'pipe', 'pipe']; + // Create a socket for writing + const pipeName = `code-stdin-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 3)}.sock`; + stdinFilePath = isWindows + ? '\\\\.\\pipe\\' + pipeName + : paths.join(os.tmpdir(), pipeName); + + // open tmp file for writing + let stdinFileError: Error; + try { + const stdErrServer = net.createServer(stream => { + process.stdin.pipe(stream); + }); + stdErrServer.listen(stdinFilePath); + } catch (error) { + stdinFileError = error; + if (verbose) { + console.error(`Failed to create file to read via stdin: ${error.toString()}`); + } + } + + if (!stdinFileError) { + argv = argv.concat('--upload-logs-stdin-pipe', stdinFilePath); + } + + options['stdio'] = ['ignore', 'pipe', 'pipe']; } else if (!verbose) { options['stdio'] = 'ignore'; } diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts index 7af1337322a93..9b598d19006d1 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts @@ -56,6 +56,7 @@ export interface ParsedArgs { 'file-write'?: boolean; 'file-chmod'?: boolean; 'upload-logs'?: boolean; + 'upload-logs-stdin-pipe'?: string; } export const IEnvironmentService = createDecorator('environmentService'); diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 251f1f6bb3bad..13e6ea3ffd91c 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -28,7 +28,8 @@ const options: minimist.Opts = { 'debugBrkSearch', 'enable-proposed-api', 'export-default-configuration', - 'install-source' + 'install-source', + 'upload-logs-stdin-pipe' ], boolean: [ 'help',