@@ -24,6 +24,7 @@ import { entries } from '../shared/utilities/tsUtils'
2424import { getEnvironmentSpecificMemento } from '../shared/utilities/mementos'
2525import { setContext } from '../shared'
2626import { telemetry } from '../shared/telemetry'
27+ import { getSessionId } from '../shared/telemetry/util'
2728
2829interface MenuOption {
2930 readonly label : string
@@ -41,6 +42,7 @@ export type DevFunction =
4142 | 'deleteSsoConnections'
4243 | 'expireSsoConnections'
4344 | 'editAuthConnections'
45+ | 'forceIdeCrash'
4446
4547export type DevOptions = {
4648 context : vscode . ExtensionContext
@@ -105,6 +107,11 @@ const menuOptions: Record<DevFunction, MenuOption> = {
105107 detail : 'Opens editor to all Auth Connections the extension is using.' ,
106108 executor : editSsoConnections ,
107109 } ,
110+ forceIdeCrash : {
111+ label : 'Crash: Force IDE ExtHost Crash' ,
112+ detail : `Will SIGKILL ExtHost, { pid: ${ process . pid } , sessionId: '${ getSessionId ( ) . slice ( 0 , 8 ) } -...' }, but the IDE itself will not crash.` ,
113+ executor : forceQuitIde ,
114+ } ,
108115}
109116
110117/**
@@ -216,6 +223,7 @@ function isSecrets(obj: vscode.Memento | vscode.SecretStorage): obj is vscode.Se
216223
217224class VirtualObjectFile implements FileProvider {
218225 private mTime = 0
226+ private size = 0
219227 private readonly onDidChangeEmitter = new vscode . EventEmitter < void > ( )
220228 public readonly onDidChange = this . onDidChangeEmitter . event
221229
@@ -227,22 +235,24 @@ class VirtualObjectFile implements FileProvider {
227235 /** Emits an event indicating this file's content has changed */
228236 public refresh ( ) {
229237 /**
230- * Per {@link vscode.FileSystemProvider.onDidChangeFile}, if the mTime does not change, new file content may
231- * not be retrieved. Without this, when we emit a change the text editor did not update.
238+ * Per {@link vscode.FileSystemProvider.onDidChangeFile}, if the mTime and/or size does not change, new file content may
239+ * not be retrieved due to optimizations . Without this, when we emit a change the text editor did not update.
232240 */
233241 this . mTime ++
234242 this . onDidChangeEmitter . fire ( )
235243 }
236244
237245 public stat ( ) : { ctime : number ; mtime : number ; size : number } {
238246 // This would need to be filled out to track conflicts
239- return { ctime : 0 , mtime : this . mTime , size : 0 }
247+ return { ctime : 0 , mtime : this . mTime , size : this . size }
240248 }
241249
242250 public async read ( ) : Promise < Uint8Array > {
243251 const encoder = new TextEncoder ( )
244252
245- return encoder . encode ( await this . readStore ( this . key ) )
253+ const data = encoder . encode ( await this . readStore ( this . key ) )
254+ this . size = data . length
255+ return data
246256 }
247257
248258 public async write ( content : Uint8Array ) : Promise < void > {
@@ -435,6 +445,15 @@ async function expireSsoConnections() {
435445 )
436446}
437447
448+ export function forceQuitIde ( ) {
449+ // This current process is the ExtensionHost. Killing it will cause all the extensions to crash
450+ // for the current ExtensionHost (unless using "extensions.experimental.affinity").
451+ // The IDE instance itself will remaing running, but a new ExtHost will spawn within it.
452+ // The PPID (parent process) is vscode itself, killing it crashes all vscode instances.
453+ const vsCodePid = process . pid
454+ process . kill ( vsCodePid , 'SIGKILL' ) // SIGTERM would be the graceful shutdown
455+ }
456+
438457async function showState ( path : string ) {
439458 const uri = vscode . Uri . parse ( `aws-dev2://state/${ path } -${ targetContext . extension . id } ` )
440459 const doc = await vscode . workspace . openTextDocument ( uri )
0 commit comments