@@ -340,6 +340,9 @@ impl WinHandle {
340
340
/// Helper struct for all data being aliased by the kernel during async reads.
341
341
#[ derive( Debug ) ]
342
342
struct AsyncData {
343
+ /// File handle of the pipe on which the async operation is performed.
344
+ handle : WinHandle ,
345
+
343
346
/// Meta-data for this async read operation, filled by the kernel.
344
347
///
345
348
/// This must be on the heap, in order for its memory location --
@@ -362,12 +365,21 @@ struct AsyncData {
362
365
#[ derive( Debug ) ]
363
366
struct MessageReader {
364
367
/// The pipe read handle.
368
+ ///
369
+ /// Note: this is only set while no async read operation
370
+ /// is currently in progress with the kernel.
371
+ /// When an async read is in progress,
372
+ /// it is moved into the `async` sub-structure (see below)
373
+ /// along with the other fields used for the async operation,
374
+ /// to make sure they all stay in sync,
375
+ /// and nothing else can meddle with the the pipe
376
+ /// until the operation is completed.
365
377
handle : WinHandle ,
366
378
367
379
/// Buffer for outstanding data, that has been received but not yet processed.
368
380
///
369
- /// Note: this is only set while no async read operation
370
- /// is currently in progress with the kernel .
381
+ /// Note: just like `handle` above,
382
+ /// this is only set while no async read is in progress .
371
383
/// When an async read is in progress,
372
384
/// the receive buffer is aliased by the kernel;
373
385
/// so we need to temporarily move it into an `AliasedCell`,
@@ -460,7 +472,7 @@ impl MessageReader {
460
472
/// and the caller should not attempt waiting for completion.
461
473
fn issue_async_cancel ( & mut self ) {
462
474
unsafe {
463
- let status = kernel32:: CancelIoEx ( self . handle . as_raw ( ) ,
475
+ let status = kernel32:: CancelIoEx ( self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ,
464
476
self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) . ov . deref_mut ( ) ) ;
465
477
466
478
if status == winapi:: FALSE {
@@ -480,7 +492,9 @@ impl MessageReader {
480
492
// and the caller should not attempt to wait for completion.
481
493
assert ! ( GetLastError ( ) == winapi:: ERROR_NOT_FOUND ) ;
482
494
483
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
495
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
496
+ self . handle = async_data. handle ;
497
+ self . read_buf = async_data. buf ;
484
498
}
485
499
}
486
500
}
@@ -537,14 +551,15 @@ impl MessageReader {
537
551
538
552
// issue the read to the buffer, at the current length offset
539
553
self . async = Some ( AliasedCell :: new ( AsyncData {
554
+ handle : self . handle . take ( ) ,
540
555
ov : Box :: new ( mem:: zeroed ( ) ) ,
541
556
buf : mem:: replace ( & mut self . read_buf , vec ! [ ] ) ,
542
557
} ) ) ;
543
558
let mut bytes_read: u32 = 0 ;
544
559
let ok = {
545
560
let async_data = self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) ;
546
561
let remaining_buf = & mut async_data. buf [ buf_len..] ;
547
- kernel32:: ReadFile ( self . handle . as_raw ( ) ,
562
+ kernel32:: ReadFile ( async_data . handle . as_raw ( ) ,
548
563
remaining_buf. as_mut_ptr ( ) as LPVOID ,
549
564
remaining_buf. len ( ) as u32 ,
550
565
& mut bytes_read,
@@ -587,11 +602,18 @@ impl MessageReader {
587
602
} ,
588
603
Err ( winapi:: ERROR_BROKEN_PIPE ) => {
589
604
win32_trace ! ( "[$ {:?}] BROKEN_PIPE straight from ReadFile" , self . handle) ;
590
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
605
+
606
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
607
+ self . handle = async_data. handle ;
608
+ self . read_buf = async_data. buf ;
609
+
591
610
Err ( WinError :: ChannelClosed )
592
611
} ,
593
612
Err ( err) => {
594
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
613
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
614
+ self . handle = async_data. handle ;
615
+ self . read_buf = async_data. buf ;
616
+
595
617
Err ( WinError :: from_system ( err, "ReadFile" ) )
596
618
} ,
597
619
}
@@ -615,12 +637,13 @@ impl MessageReader {
615
637
/// between receiving the completion notification from the kernel
616
638
/// and invoking this method.
617
639
unsafe fn notify_completion ( & mut self , io_result : Result < ( ) , WinError > ) -> Result < ( ) , WinError > {
618
- win32_trace ! ( "[$ {:?}] notify_completion" , self . handle) ;
640
+ win32_trace ! ( "[$ {:?}] notify_completion" , self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle) ;
619
641
620
642
// Regardless whether the kernel reported success or error,
621
643
// it doesn't have an async read operation in flight at this point anymore.
622
644
// (And it's safe again to access the `async` data.)
623
645
let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
646
+ self . handle = async_data. handle ;
624
647
let ov = async_data. ov ;
625
648
self . read_buf = async_data. buf ;
626
649
@@ -671,7 +694,7 @@ impl MessageReader {
671
694
BlockingMode :: Blocking => winapi:: TRUE ,
672
695
BlockingMode :: Nonblocking => winapi:: FALSE ,
673
696
} ;
674
- let ok = kernel32:: GetOverlappedResult ( self . handle . as_raw ( ) ,
697
+ let ok = kernel32:: GetOverlappedResult ( self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ,
675
698
self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) . ov . deref_mut ( ) ,
676
699
& mut nbytes,
677
700
block) ;
@@ -1399,7 +1422,10 @@ impl OsIpcReceiverSet {
1399
1422
1400
1423
// Find the matching receiver
1401
1424
let ( reader_index, _) = self . readers . iter ( ) . enumerate ( )
1402
- . find ( |& ( _, ref reader) | reader. handle . as_raw ( ) as winapi:: ULONG_PTR == completion_key)
1425
+ . find ( |& ( _, ref reader) | {
1426
+ let raw_handle = reader. async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ;
1427
+ raw_handle as winapi:: ULONG_PTR == completion_key
1428
+ } )
1403
1429
. expect ( "Windows IPC ReceiverSet got notification for a receiver it doesn't know about" ) ;
1404
1430
1405
1431
// Remove the entry from the set for now -- we will re-add it later,
0 commit comments