@@ -12,7 +12,7 @@ import { commands, StatusBarItem, Uri, ViewColumn, Webview, window, workspace, e
1212
1313import { runTextInTerm } from './rTerminal' ;
1414import { FSWatcher } from 'fs-extra' ;
15- import { config , readContent , setContext , UriIcon } from './util' ;
15+ import { config , createWaiterForInvoker , readContent , setContext , UriIcon } from './util' ;
1616import { purgeAddinPickerItems , dispatchRStudioAPICall } from './rstudioapi' ;
1717
1818import { IRequest } from './liveShare/shareSession' ;
@@ -74,12 +74,28 @@ let activeBrowserExternalUri: Uri | undefined;
7474export let incomingRequestServerAddressInfo : AddressInfo | undefined = undefined ;
7575export let attached = false ;
7676
77- class AnotherSocketConnectionError extends Error {
78- finishCleaningCallback : ( ) => void ;
77+ enum InterruptReason {
78+ ANOTHER_CONNECTION ,
79+ USER_REQUEST
80+ }
81+
82+ class InterruptSocketConnectionError extends Error {
83+ reason : InterruptReason ;
84+ finishWaiter : Promise < void > ;
85+ private finishInvoker : ( ) => void ;
7986
80- constructor ( finishCleaningCallback : ( ) => void ) {
87+ constructor ( reason : InterruptReason ) {
8188 super ( ) ;
82- this . finishCleaningCallback = finishCleaningCallback ;
89+
90+ this . reason = reason ;
91+
92+ const pair = createWaiterForInvoker ( ) ;
93+ this . finishWaiter = pair . waiter ;
94+ this . finishInvoker = pair . invoker ;
95+ }
96+
97+ reportFinishHandling ( ) {
98+ this . finishInvoker ( ) ;
8399 }
84100}
85101
@@ -339,6 +355,17 @@ function getBrowserHtml(uri: Uri): string {
339355` ;
340356}
341357
358+ export async function detach ( ) {
359+ if ( incomingRequestServerCurrentSocket === null ) {
360+ return ;
361+ }
362+ // otherwise
363+
364+ const interrupt = new InterruptSocketConnectionError ( InterruptReason . USER_REQUEST ) ;
365+ incomingRequestServerCurrentSocket . destroy ( interrupt ) ;
366+ await interrupt . finishWaiter ;
367+ }
368+
342369export function refreshBrowser ( ) : void {
343370 console . log ( '[refreshBrowser]' ) ;
344371 if ( activeBrowserPanel ) {
@@ -835,22 +862,9 @@ function startIncomingRequestServer(sessionStatusBarItem: StatusBarItem) {
835862 if ( incomingRequestServerCurrentSocket !== null ) {
836863 console . info ( 'Closing existing connection to the incoming request server since a new one is pending.' ) ;
837864
838- let resolveHandle : ( ( ) => void ) | null = null ;
839- let wasHandledQuick = false ;
840- const promise = new Promise < void > ( ( resolve ) => {
841- resolveHandle = resolve ;
842- } ) ;
843- const callback = ( ) => {
844- if ( resolveHandle === null ) {
845- wasHandledQuick = true ;
846- } else {
847- resolveHandle ( ) ;
848- }
849- } ;
850- incomingRequestServerCurrentSocket . destroy ( new AnotherSocketConnectionError ( callback ) ) ;
851- if ( ! wasHandledQuick ) {
852- await promise ;
853- }
865+ const interrupt = new InterruptSocketConnectionError ( InterruptReason . ANOTHER_CONNECTION ) ;
866+ incomingRequestServerCurrentSocket . destroy ( interrupt ) ;
867+ await interrupt . finishWaiter ;
854868 }
855869
856870 console . info ( 'A new connection to the incoming request server has been established.' ) ;
@@ -893,20 +907,29 @@ function startIncomingRequestServer(sessionStatusBarItem: StatusBarItem) {
893907 contentToProcess = requests [ requests . length - 1 ] ;
894908 }
895909 } catch ( err ) {
896- if ( err instanceof AnotherSocketConnectionError ) {
897- console . error ( `Closing this TCP connection since another one is pending.` ) ;
910+ if ( err instanceof InterruptSocketConnectionError ) {
911+ switch ( err . reason ) {
912+ case InterruptReason . ANOTHER_CONNECTION :
913+ console . log ( `Closing this TCP connection since another one is pending.` ) ;
914+ break ;
915+ case InterruptReason . USER_REQUEST :
916+ console . log ( `Closing this TCP connection because of a user request.` ) ;
917+ break ;
918+ }
898919 } else {
899920 // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
900921 console . error ( `Error while processing TCP connection: ${ err } ` ) ;
901922 }
902923
903- void promiseSocket . end ( ) ;
924+ void promiseSocket . end ( ) . catch ( ( ) => {
925+ // For some reason, there is an error when ending this connection, so we're ignoring the error for now
926+ } ) ;
904927
905928 await cleanupSession ( ) ;
906929 incomingRequestServerCurrentSocket = null ;
907930
908- if ( err instanceof AnotherSocketConnectionError ) {
909- err . finishCleaningCallback ( ) ;
931+ if ( err instanceof InterruptSocketConnectionError ) {
932+ err . reportFinishHandling ( ) ;
910933 }
911934 }
912935 } ) ;
0 commit comments