@@ -65,24 +65,33 @@ export class MainRuntime implements KernelRuntime {
6565 } ) ;
6666
6767 // 5. Pipe stdin (with auth) → worker (write half)
68- // We do NOT prevent close here. When stdin closes, we want to close the write half of the socket.
69- // This signals EOF to the worker's reader.
70- const stdinPipe = stdinWithAuth . pipeTo ( conn . writable ) . catch ( ( ) => { } ) ;
68+ // Use half-close (SHUT_WR) to signal EOF while keeping read end open.
69+ const stdinPipe = stdinWithAuth . pipeTo ( conn . writable , { preventClose : true } )
70+ . then ( ( ) => {
71+ try {
72+ // @ts -ignore: closeWrite is available on UnixConn
73+ conn . closeWrite ( ) ;
74+ } catch ( e ) {
75+ console . error ( `[Main] Error half-closing socket: ${ e } ` ) ;
76+ }
77+ } )
78+ . catch ( ( ) => { } ) ;
7179
7280 // 6. Pipe worker → stdout (read half)
7381 // We need to detect when the worker has finished replying to our request.
74- const stdoutPipe = conn . readable . pipeTo ( Deno . stdout . writable ) . catch ( ( ) => { } ) ;
82+ const stdoutPipe = conn . readable
83+ . pipeTo ( Deno . stdout . writable , { preventClose : true } ) . catch ( ( ) => { } ) ;
7584
7685 // 7. Wait for both pipes to complete
7786 await Promise . all ( [ stdinPipe , stdoutPipe ] ) ;
7887
7988 // 8. Explicitly close stdout to ensure the process exits cleanly
8089 // This is sometimes needed if Deno.stdout is kept open by other things
81- try {
82- Deno . stdout . close ( ) ;
83- } catch {
90+ // try {
91+ // Deno.stdout.close();
92+ // } catch {
8493 // Ignore
85- }
94+ // }
8695
8796 return 0 ;
8897 } catch ( e : unknown ) {
@@ -170,13 +179,17 @@ export class MainRuntime implements KernelRuntime {
170179 private async waitForSocket ( path : string ) : Promise < Deno . UnixConn > {
171180 const dir = dirname ( path ) ;
172181 const filename = path . split ( "/" ) . pop ( ) ! ;
182+ const tryConnect = async ( ) : Promise < Deno . UnixConn | null > => {
183+ try {
184+ return await Deno . connect ( { transport : "unix" , path } ) as Deno . UnixConn ;
185+ } catch {
186+ return null ;
187+ }
188+ } ;
173189
174190 // Try connecting immediately just in case
175- try {
176- return await Deno . connect ( { transport : "unix" , path } ) as Deno . UnixConn ;
177- } catch {
178- // Ignore
179- }
191+ const immediate = await tryConnect ( ) ;
192+ if ( immediate ) return immediate ;
180193
181194 // Watch for creation
182195 let watcher : Deno . FsWatcher ;
@@ -189,40 +202,29 @@ export class MainRuntime implements KernelRuntime {
189202
190203 const timeout = 5000 ; // 5s timeout
191204 const start = Date . now ( ) ;
205+ const iterator = watcher [ Symbol . asyncIterator ] ( ) ;
206+ const sleep = ( ms : number ) => new Promise < "tick" > ( ( resolve ) => setTimeout ( ( ) => resolve ( "tick" ) , ms ) ) ;
192207
193208 try {
194- // Race: Watcher vs Timeout
195- // We loop because the watcher might fire for other files
209+ // Event-driven loop with deterministic liveness polling
196210 while ( Date . now ( ) - start < timeout ) {
197- // Create a promise for the next relevant event
198- const nextEvent = new Promise < void > ( ( resolve ) => {
199- ( async ( ) => {
200- try {
201- for await ( const event of watcher ) {
202- if ( event . kind === "create" || event . kind === "modify" ) {
203- if ( event . paths . some ( p => p . endsWith ( filename ) ) ) {
204- resolve ( ) ;
205- return ;
206- }
207- }
208- }
209- } catch ( e ) {
210- // Watcher closed or error
211- }
212- } ) ( ) ;
213- } ) ;
214-
215- // Wait for event or short timeout (to retry connect)
216- await Promise . race ( [
217- nextEvent ,
218- new Promise ( ( r ) => setTimeout ( r , 100 ) )
211+ const conn = await tryConnect ( ) ;
212+ if ( conn ) return conn ;
213+
214+ const remaining = Math . max ( 0 , start + timeout - Date . now ( ) ) ;
215+ const waitMs = Math . min ( 50 , remaining ) ;
216+ const result = await Promise . race ( [
217+ iterator . next ( ) ,
218+ sleep ( waitMs ) ,
219219 ] ) ;
220220
221- // Try connecting
222- try {
223- return await Deno . connect ( { transport : "unix" , path } ) as Deno . UnixConn ;
224- } catch {
225- // Continue waiting
221+ if ( result !== "tick" && ! result . done ) {
222+ const event = result . value ;
223+ if ( ( event . kind === "create" || event . kind === "modify" ) &&
224+ event . paths . some ( ( p ) => p . endsWith ( filename ) ) ) {
225+ const afterEvent = await tryConnect ( ) ;
226+ if ( afterEvent ) return afterEvent ;
227+ }
226228 }
227229 }
228230 } catch ( e ) {
0 commit comments