@@ -83,7 +83,7 @@ export function hasTrustedCompilerPaths(): boolean {
8383
8484// Data shared by all clients.
8585let languageClient : LanguageClient ;
86- let firstClientStarted : Promise < void > ;
86+ let firstClientStarted : Promise < boolean > ;
8787let languageClientCrashedNeedsRestart : boolean = false ;
8888const languageClientCrashTimes : number [ ] = [ ] ;
8989let compilerDefaults : configs . CompilerDefaults | undefined ;
@@ -1191,34 +1191,36 @@ export class DefaultClient implements Client {
11911191 const rootUri : vscode . Uri | undefined = this . RootUri ;
11921192 this . settingsTracker = new SettingsTracker ( rootUri ) ;
11931193
1194- try {
1195- let isFirstClient : boolean = false ;
1196- if ( ! languageClient || languageClientCrashedNeedsRestart ) {
1197- if ( languageClientCrashedNeedsRestart ) {
1198- languageClientCrashedNeedsRestart = false ;
1199- // if we're recovering, the isStarted needs to be reset.
1200- // because we're starting the first client again.
1201- DefaultClient . isStarted . reset ( ) ;
1202- }
1203- firstClientStarted = this . createLanguageClient ( ) ;
1204- util . setProgress ( util . getProgressExecutableStarted ( ) ) ;
1205- isFirstClient = true ;
1206- }
1207- void this . init ( rootUri , isFirstClient ) . catch ( logAndReturn . undefined ) ;
1208-
1209- } catch ( errJS ) {
1210- const err : NodeJS . ErrnoException = errJS as NodeJS . ErrnoException ;
1211- this . isSupported = false ; // Running on an OS we don't support yet.
1212- if ( ! failureMessageShown ) {
1213- failureMessageShown = true ;
1214- let additionalInfo : string ;
1215- if ( err . code === "EPERM" ) {
1216- additionalInfo = localize ( 'check.permissions' , "EPERM: Check permissions for '{0}'" , getLanguageServerFileName ( ) ) ;
1217- } else {
1218- additionalInfo = String ( err ) ;
1194+ let isFirstClient : boolean = false ;
1195+ if ( ! languageClient || languageClientCrashedNeedsRestart ) {
1196+ if ( languageClientCrashedNeedsRestart ) {
1197+ languageClientCrashedNeedsRestart = false ;
1198+ // if we're recovering, the isStarted needs to be reset.
1199+ // because we're starting the first client again.
1200+ DefaultClient . isStarted . reset ( ) ;
1201+ }
1202+ isFirstClient = true ;
1203+ firstClientStarted = this . createLanguageClient ( ) ;
1204+ firstClientStarted . catch ( ( errJS ) => {
1205+ const err : NodeJS . ErrnoException = errJS as NodeJS . ErrnoException ;
1206+ this . isSupported = false ; // Running on an OS we don't support yet.
1207+ if ( ! failureMessageShown ) {
1208+ failureMessageShown = true ;
1209+ let additionalInfo : string ;
1210+ if ( err . code === "EPERM" ) {
1211+ additionalInfo = localize ( 'check.permissions' , "EPERM: Check permissions for '{0}'" , getLanguageServerFileName ( ) ) ;
1212+ } else {
1213+ additionalInfo = String ( err ) ;
1214+ }
1215+ void vscode . window . showErrorMessage ( localize ( "unable.to.start" , "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}" , additionalInfo ) ) ;
12191216 }
1220- void vscode . window . showErrorMessage ( localize ( "unable.to.start" , "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}" , additionalInfo ) ) ;
1221- }
1217+ } ) ;
1218+ firstClientStarted . then ( ( success ) => {
1219+ if ( success ) {
1220+ util . setProgress ( util . getProgressExecutableStarted ( ) ) ;
1221+ void this . init ( rootUri , isFirstClient ) . catch ( logAndReturn . undefined ) ;
1222+ }
1223+ } , logAndReturn . undefined ) ;
12221224 }
12231225 }
12241226
@@ -1464,7 +1466,7 @@ export class DefaultClient implements Client {
14641466 } ;
14651467 }
14661468
1467- private async createLanguageClient ( ) : Promise < void > {
1469+ private async createLanguageClient ( ) : Promise < boolean > {
14681470 const currentCaseSensitiveFileSupport : PersistentWorkspaceState < boolean > = new PersistentWorkspaceState < boolean > ( "CPP.currentCaseSensitiveFileSupport" , false ) ;
14691471 let resetDatabase : boolean = false ;
14701472 const serverModule : string = getLanguageServerFileName ( ) ;
@@ -1580,12 +1582,25 @@ export class DefaultClient implements Client {
15801582 languageClient . onNotification ( DebugProtocolNotification , logDebugProtocol ) ;
15811583 languageClient . onNotification ( DebugLogNotification , logLocalized ) ;
15821584 languageClient . registerProposedFeatures ( ) ;
1583- await languageClient . start ( ) ;
1585+
1586+ // If thisLanguageClient.start() were to trigger our errorHandler.closed, it may interrupt us
1587+ // (since we're calling await here) and overwrite `languageClient`. Use a new var to ensure we
1588+ // don't attempt to sent multiple initialization messages.
1589+ const thisLanguageClient : LanguageClient = languageClient ;
1590+ await thisLanguageClient . start ( ) ;
1591+ if ( thisLanguageClient !== languageClient ) {
1592+ return false ;
1593+ }
15841594
15851595 // Move initialization to a separate message, so we can see log output from it.
15861596 // A request is used in order to wait for completion and ensure that no subsequent
15871597 // higher priority message may be processed before the Initialization request.
1588- watchForCrashes ( await languageClient . sendRequest ( InitializationRequest , cppInitializationParams ) ) ;
1598+ const crashPath : string = await thisLanguageClient . sendRequest ( InitializationRequest , cppInitializationParams ) ;
1599+ if ( crashPath ) {
1600+ // empty string may be returned in error cases.
1601+ watchForCrashes ( crashPath ) ;
1602+ }
1603+ return true ;
15891604 }
15901605
15911606 public async sendDidChangeSettings ( ) : Promise < void > {
0 commit comments