@@ -68,14 +68,11 @@ export async function startDapServer(
68
68
} else {
69
69
configuration . port = await getPort ( ) ;
70
70
}
71
- const dlvDapServer = spawnDlvDapServerProcess ( configuration ) ;
72
- // Wait to give dlv-dap a chance to start before returning.
73
- return await new Promise < { port : number ; host : string ; dlvDapServer : ChildProcessWithoutNullStreams } > ( ( resolve ) =>
74
- setTimeout ( ( ) => resolve ( { port : configuration . port , host : configuration . host , dlvDapServer } ) , 500 )
75
- ) ;
71
+ const dlvDapServer = await spawnDlvDapServerProcess ( configuration ) ;
72
+ return { dlvDapServer, port : configuration . port , host : configuration . host } ;
76
73
}
77
74
78
- function spawnDlvDapServerProcess ( launchArgs : DebugConfiguration ) {
75
+ async function spawnDlvDapServerProcess ( launchArgs : DebugConfiguration ) : Promise < ChildProcess > {
79
76
const launchArgsEnv = launchArgs . env || { } ;
80
77
const env = Object . assign ( { } , process . env , launchArgsEnv ) ;
81
78
@@ -114,30 +111,66 @@ function spawnDlvDapServerProcess(launchArgs: DebugConfiguration) {
114
111
appendToDebugConsole ( `Running: ${ dlvPath } ${ dlvArgs . join ( ' ' ) } ` ) ;
115
112
116
113
const dir = parseProgramArgSync ( launchArgs ) . dirname ;
117
- const p = spawn ( dlvPath , dlvArgs , {
118
- cwd : dir ,
119
- env
120
- } ) ;
121
114
122
- p . stderr . on ( 'data' , ( chunk ) => {
123
- appendToDebugConsole ( chunk . toString ( ) ) ;
124
- } ) ;
125
- p . stdout . on ( 'data' , ( chunk ) => {
126
- appendToDebugConsole ( chunk . toString ( ) ) ;
127
- } ) ;
128
- p . on ( 'close' , ( code ) => {
129
- if ( code ) {
130
- appendToDebugConsole ( `Process exiting with code: ${ code } signal: ${ p . killed } ` ) ;
131
- } else {
132
- appendToDebugConsole ( `Process exited normally: ${ p . killed } ` ) ;
133
- }
134
- } ) ;
135
- p . on ( 'error' , ( err ) => {
136
- if ( err ) {
137
- appendToDebugConsole ( `Error: ${ err } ` ) ;
138
- }
115
+ return await new Promise < ChildProcess > ( ( resolve , reject ) => {
116
+ const p = spawn ( dlvPath , dlvArgs , {
117
+ cwd : dir ,
118
+ env
119
+ } ) ;
120
+ let started = false ;
121
+ const timeoutToken : NodeJS . Timer = setTimeout (
122
+ ( ) => reject ( new Error ( 'timed out while waiting for DAP server to start' ) ) ,
123
+ 5_000
124
+ ) ;
125
+
126
+ const stopWaitingForServerToStart = ( err ?: string ) => {
127
+ clearTimeout ( timeoutToken ) ;
128
+ started = true ;
129
+ if ( err ) {
130
+ killProcessTree ( p ) ; // We do not need to wait for p to actually be killed.
131
+ reject ( new Error ( err ) ) ;
132
+ } else {
133
+ resolve ( p ) ;
134
+ }
135
+ } ;
136
+
137
+ p . stdout . on ( 'data' , ( chunk ) => {
138
+ if ( ! started ) {
139
+ if ( chunk . toString ( ) . startsWith ( 'DAP server listening at:' ) ) {
140
+ stopWaitingForServerToStart ( ) ;
141
+ } else {
142
+ stopWaitingForServerToStart (
143
+ `Expected 'DAP server listening at:' from debug adapter got '${ chunk . toString ( ) } '`
144
+ ) ;
145
+ }
146
+ }
147
+ appendToDebugConsole ( chunk . toString ( ) ) ;
148
+ } ) ;
149
+ p . stderr . on ( 'data' , ( chunk ) => {
150
+ if ( ! started ) {
151
+ stopWaitingForServerToStart ( `Unexpected error from dlv dap on start: '${ chunk . toString ( ) } '` ) ;
152
+ }
153
+ appendToDebugConsole ( chunk . toString ( ) ) ;
154
+ } ) ;
155
+ p . on ( 'close' , ( code ) => {
156
+ if ( ! started ) {
157
+ stopWaitingForServerToStart ( `dlv dap closed with code: '${ code } ' signal: ${ p . killed } ` ) ;
158
+ }
159
+ if ( code ) {
160
+ appendToDebugConsole ( `Process exiting with code: ${ code } signal: ${ p . killed } ` ) ;
161
+ } else {
162
+ appendToDebugConsole ( `Process exited normally: ${ p . killed } ` ) ;
163
+ }
164
+ } ) ;
165
+ p . on ( 'error' , ( err ) => {
166
+ if ( ! started ) {
167
+ stopWaitingForServerToStart ( `Unexpected error from dlv dap on start: '${ err } '` ) ;
168
+ }
169
+ if ( err ) {
170
+ appendToDebugConsole ( `Error: ${ err } ` ) ;
171
+ }
172
+ } ) ;
139
173
} ) ;
140
- return p ;
141
174
}
142
175
143
176
function parseProgramArgSync (
0 commit comments