diff --git a/src/vs/workbench/services/search/node/textSearch.ts b/src/vs/workbench/services/search/node/textSearch.ts index 890eca5bd13a7b981955e0b1f7e094df6909f85c..51ede2e50f7dd1e231c97c45b26cb43cbdea54db 100644 --- a/src/vs/workbench/services/search/node/textSearch.ts +++ b/src/vs/workbench/services/search/node/textSearch.ts @@ -12,6 +12,7 @@ import * as path from 'path'; import * as ipc from 'vs/base/parts/ipc/common/ipc'; +import { onUnexpectedError } from 'vs/base/common/errors'; import { IProgress } from 'vs/platform/search/common/search'; import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; import { ISerializedFileMatch, ISerializedSearchComplete, IRawSearch, ISearchEngine } from './search'; @@ -49,7 +50,10 @@ export class Engine implements ISearchEngine { this.isCanceled = true; this.walker.cancel(); - this.workers.forEach(w => w.cancel()); + this.workers.forEach(w => { + w.cancel() + .then(null, onUnexpectedError); + }); } search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { @@ -102,7 +106,12 @@ export class Engine implements ISearchEngine { } unwind(batchBytes); - }); + }, + error => { + // An error on the worker's end, not in reading the file, but in processing the batch. Log and continue. + onUnexpectedError(error); + unwind(batchBytes); + }); }; // Walk over the file system @@ -170,7 +179,7 @@ export class Engine implements ISearchEngine { const channel = ipc.getNextTickChannel(client.getChannel('searchWorker')); const channelClient = new SearchWorkerChannelClient(channel); const config: ISearchWorkerConfig = { pattern: this.config.contentPattern, id, fileEncoding: this.config.fileEncoding }; - channelClient.initialize(config); + channelClient.initialize(config).then(null, onUnexpectedError); this.workers.push(channelClient); this.workerClients.push(client); diff --git a/src/vs/workbench/services/search/node/worker/searchWorker.ts b/src/vs/workbench/services/search/node/worker/searchWorker.ts index a186d58010773a85b13651631f8980c76737945d..d79b691ed7cd38ff2dfd5633a9a9c9f30af7ec13 100644 --- a/src/vs/workbench/services/search/node/worker/searchWorker.ts +++ b/src/vs/workbench/services/search/node/worker/searchWorker.ts @@ -7,6 +7,7 @@ import * as fs from 'fs'; +import { onUnexpectedError } from 'vs/base/common/errors'; import * as strings from 'vs/base/common/strings'; import { TPromise } from 'vs/base/common/winjs.base'; import { ISerializedFileMatch } from '../search'; @@ -25,6 +26,14 @@ interface ReadLinesOptions { // Global isCanceled flag for the process. It's only set once and this avoids awkwardness in passing it around. let isCanceled = false; +const MAX_FILE_ERRORS = 5; // Don't report more than this number of errors, 1 per file, to avoid flooding the log when there's a general issue +let numErrorsLogged = 0; +function onError(error: any): void { + if (numErrorsLogged++ < MAX_FILE_ERRORS) { + onUnexpectedError(error); + } +} + export class SearchWorker implements ISearchWorker { static CONCURRENT_SEARCH_PATHS = 2; @@ -89,7 +98,7 @@ function searchBatch(absolutePaths: string[], contentPattern: RegExp, fileEncodi if (absolutePaths.length) { return startSearchInFile(absolutePaths.shift()); } - }); + }, onError); }; let batchPromises: TPromise[] = []; diff --git a/src/vs/workbench/services/search/node/worker/searchWorkerIpc.ts b/src/vs/workbench/services/search/node/worker/searchWorkerIpc.ts index 9b30d5184370afa34dfc183e3a57d5c9fbf40ed5..045c725d4bb104b390db4684547ce2c20a4ee7f0 100644 --- a/src/vs/workbench/services/search/node/worker/searchWorkerIpc.ts +++ b/src/vs/workbench/services/search/node/worker/searchWorkerIpc.ts @@ -47,7 +47,7 @@ export class SearchWorkerChannel implements ISearchWorkerChannel { call(command: string, arg?: any): TPromise { switch (command) { - case 'initialize': return TPromise.wrap(this.worker.initialize(arg)); + case 'initialize': return this.worker.initialize(arg); case 'search': return this.worker.search(arg); case 'cancel': return this.worker.cancel(); }