未验证 提交 35eb83ec 编写于 作者: M Martin Aeschlimann 提交者: GitHub

Merge pull request #76009 from microsoft/aeschli/pollingForWSL1

File watcher: use polling for wsl1
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { mkdir, open, close, read, write, fdatasync } from 'fs'; import { mkdir, open, close, read, write, fdatasync } from 'fs';
import * as os from 'os';
import { promisify } from 'util'; import { promisify } from 'util';
import { IDisposable, Disposable, toDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle'; import { IDisposable, Disposable, toDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
import { IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, FileSystemProviderErrorCode, createFileSystemProviderError, FileSystemProviderError } from 'vs/platform/files/common/files'; import { IFileSystemProvider, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileType, FileDeleteOptions, FileOverwriteOptions, FileWriteOptions, FileOpenOptions, FileSystemProviderErrorCode, createFileSystemProviderError, FileSystemProviderError } from 'vs/platform/files/common/files';
...@@ -408,22 +409,30 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro ...@@ -408,22 +409,30 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
folders: { path: string, excludes: string[] }[], folders: { path: string, excludes: string[] }[],
onChange: (changes: IDiskFileChange[]) => void, onChange: (changes: IDiskFileChange[]) => void,
onLogMessage: (msg: ILogMessage) => void, onLogMessage: (msg: ILogMessage) => void,
verboseLogging: boolean verboseLogging: boolean,
watcherOptions?: { [key: string]: boolean | number | string }
): WindowsWatcherService | UnixWatcherService | NsfwWatcherService ): WindowsWatcherService | UnixWatcherService | NsfwWatcherService
}; };
let watcherOptions = undefined;
// Single Folder Watcher
if (this.recursiveFoldersToWatch.length === 1) { if (this.forcePolling()) {
if (isWindows) { // WSL needs a polling watcher
watcherImpl = WindowsWatcherService; watcherImpl = UnixWatcherService;
} else { watcherOptions = { usePolling: true };
watcherImpl = UnixWatcherService; } else {
// Single Folder Watcher
if (this.recursiveFoldersToWatch.length === 1) {
if (isWindows) {
watcherImpl = WindowsWatcherService;
} else {
watcherImpl = UnixWatcherService;
}
} }
}
// Multi Folder Watcher // Multi Folder Watcher
else { else {
watcherImpl = NsfwWatcherService; watcherImpl = NsfwWatcherService;
}
} }
// Create and start watching // Create and start watching
...@@ -436,7 +445,8 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro ...@@ -436,7 +445,8 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
} }
this.logService[msg.type](msg.message); this.logService[msg.type](msg.message);
}, },
this.logService.getLevel() === LogLevel.Trace this.logService.getLevel() === LogLevel.Trace,
watcherOptions
); );
if (!this.recursiveWatcherLogLevelListener) { if (!this.recursiveWatcherLogLevelListener) {
...@@ -504,6 +514,12 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro ...@@ -504,6 +514,12 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
return createFileSystemProviderError(error, code); return createFileSystemProviderError(error, code);
} }
forcePolling(): boolean {
// wsl1 needs polling
return isLinux && /^[\.\-0-9]+-Microsoft/.test(os.release());
}
//#endregion //#endregion
dispose(): void { dispose(): void {
......
...@@ -23,10 +23,6 @@ interface IWatcher { ...@@ -23,10 +23,6 @@ interface IWatcher {
stop(): any; stop(): any;
} }
export interface IChockidarWatcherOptions {
pollingInterval?: number;
}
interface ExtendedWatcherRequest extends IWatcherRequest { interface ExtendedWatcherRequest extends IWatcherRequest {
parsedPattern?: glob.ParsedPattern; parsedPattern?: glob.ParsedPattern;
} }
...@@ -40,6 +36,7 @@ export class ChokidarWatcherService implements IWatcherService { ...@@ -40,6 +36,7 @@ export class ChokidarWatcherService implements IWatcherService {
private _watcherCount: number; private _watcherCount: number;
private _pollingInterval?: number; private _pollingInterval?: number;
private _usePolling?: boolean;
private _verboseLogging: boolean; private _verboseLogging: boolean;
private spamCheckStartTime: number; private spamCheckStartTime: number;
...@@ -52,8 +49,9 @@ export class ChokidarWatcherService implements IWatcherService { ...@@ -52,8 +49,9 @@ export class ChokidarWatcherService implements IWatcherService {
private _onLogMessage = new Emitter<ILogMessage>(); private _onLogMessage = new Emitter<ILogMessage>();
readonly onLogMessage: Event<ILogMessage> = this._onLogMessage.event; readonly onLogMessage: Event<ILogMessage> = this._onLogMessage.event;
public watch(options: IWatcherOptions & IChockidarWatcherOptions): Event<IDiskFileChange[]> { public watch(options: IWatcherOptions): Event<IDiskFileChange[]> {
this._pollingInterval = options.pollingInterval; this._pollingInterval = options.pollingInterval;
this._usePolling = options.usePolling;
this._watchers = Object.create(null); this._watchers = Object.create(null);
this._watcherCount = 0; this._watcherCount = 0;
return this.onWatchEvent; return this.onWatchEvent;
...@@ -106,6 +104,10 @@ export class ChokidarWatcherService implements IWatcherService { ...@@ -106,6 +104,10 @@ export class ChokidarWatcherService implements IWatcherService {
} }
const pollingInterval = this._pollingInterval || 1000; const pollingInterval = this._pollingInterval || 1000;
const usePolling = this._usePolling;
if (usePolling && this._verboseLogging) {
this.log(`Use polling instead of fs.watch: Polling interval ${pollingInterval} ms`);
}
const watcherOpts: chokidar.IOptions = { const watcherOpts: chokidar.IOptions = {
ignoreInitial: true, ignoreInitial: true,
...@@ -113,6 +115,7 @@ export class ChokidarWatcherService implements IWatcherService { ...@@ -113,6 +115,7 @@ export class ChokidarWatcherService implements IWatcherService {
followSymlinks: true, // this is the default of chokidar and supports file events through symlinks followSymlinks: true, // this is the default of chokidar and supports file events through symlinks
interval: pollingInterval, // while not used in normal cases, if any error causes chokidar to fallback to polling, increase its intervals interval: pollingInterval, // while not used in normal cases, if any error causes chokidar to fallback to polling, increase its intervals
binaryInterval: pollingInterval, binaryInterval: pollingInterval,
usePolling: usePolling,
disableGlobbing: true // fix https://github.com/Microsoft/vscode/issues/4586 disableGlobbing: true // fix https://github.com/Microsoft/vscode/issues/4586
}; };
......
...@@ -12,6 +12,8 @@ export interface IWatcherRequest { ...@@ -12,6 +12,8 @@ export interface IWatcherRequest {
} }
export interface IWatcherOptions { export interface IWatcherOptions {
pollingInterval?: number;
usePolling?: boolean;
} }
export interface IWatcherService { export interface IWatcherService {
......
...@@ -8,7 +8,7 @@ import { Client } from 'vs/base/parts/ipc/node/ipc.cp'; ...@@ -8,7 +8,7 @@ import { Client } from 'vs/base/parts/ipc/node/ipc.cp';
import { IDiskFileChange, ILogMessage } from 'vs/workbench/services/files/node/watcher/watcher'; import { IDiskFileChange, ILogMessage } from 'vs/workbench/services/files/node/watcher/watcher';
import { WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/unix/watcherIpc'; import { WatcherChannelClient } from 'vs/workbench/services/files/node/watcher/unix/watcherIpc';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IWatcherRequest } from 'vs/workbench/services/files/node/watcher/unix/watcher'; import { IWatcherRequest, IWatcherOptions } from 'vs/workbench/services/files/node/watcher/unix/watcher';
import { getPathFromAmdModule } from 'vs/base/common/amd'; import { getPathFromAmdModule } from 'vs/base/common/amd';
export class FileWatcher extends Disposable { export class FileWatcher extends Disposable {
...@@ -22,7 +22,8 @@ export class FileWatcher extends Disposable { ...@@ -22,7 +22,8 @@ export class FileWatcher extends Disposable {
private folders: IWatcherRequest[], private folders: IWatcherRequest[],
private onFileChanges: (changes: IDiskFileChange[]) => void, private onFileChanges: (changes: IDiskFileChange[]) => void,
private onLogMessage: (msg: ILogMessage) => void, private onLogMessage: (msg: ILogMessage) => void,
private verboseLogging: boolean private verboseLogging: boolean,
private watcherOptions: IWatcherOptions = {}
) { ) {
super(); super();
...@@ -66,8 +67,7 @@ export class FileWatcher extends Disposable { ...@@ -66,8 +67,7 @@ export class FileWatcher extends Disposable {
this.service.setVerboseLogging(this.verboseLogging); this.service.setVerboseLogging(this.verboseLogging);
const options = {}; this._register(this.service.watch(this.watcherOptions)(e => !this.isDisposed && this.onFileChanges(e)));
this._register(this.service.watch(options)(e => !this.isDisposed && this.onFileChanges(e)));
this._register(this.service.onLogMessage(m => this.onLogMessage(m))); this._register(this.service.onLogMessage(m => this.onLogMessage(m)));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册