@@ -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`,
@@ -466,7 +478,7 @@ impl MessageReader {
466
478
/// and the caller should not attempt waiting for completion.
467
479
fn issue_async_cancel ( & mut self ) {
468
480
unsafe {
469
- let status = kernel32:: CancelIoEx ( self . handle . as_raw ( ) ,
481
+ let status = kernel32:: CancelIoEx ( self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ,
470
482
self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) . ov . deref_mut ( ) ) ;
471
483
472
484
if status == winapi:: FALSE {
@@ -486,7 +498,9 @@ impl MessageReader {
486
498
// and the caller should not attempt to wait for completion.
487
499
assert ! ( GetLastError ( ) == winapi:: ERROR_NOT_FOUND ) ;
488
500
489
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
501
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
502
+ self . handle = async_data. handle ;
503
+ self . read_buf = async_data. buf ;
490
504
}
491
505
}
492
506
}
@@ -543,14 +557,15 @@ impl MessageReader {
543
557
544
558
// issue the read to the buffer, at the current length offset
545
559
self . async = Some ( AliasedCell :: new ( AsyncData {
560
+ handle : self . handle . take ( ) ,
546
561
ov : Box :: new ( mem:: zeroed ( ) ) ,
547
562
buf : mem:: replace ( & mut self . read_buf , vec ! [ ] ) ,
548
563
} ) ) ;
549
564
let mut bytes_read: u32 = 0 ;
550
565
let ok = {
551
566
let async_data = self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) ;
552
567
let remaining_buf = & mut async_data. buf [ buf_len..] ;
553
- kernel32:: ReadFile ( self . handle . as_raw ( ) ,
568
+ kernel32:: ReadFile ( async_data . handle . as_raw ( ) ,
554
569
remaining_buf. as_mut_ptr ( ) as LPVOID ,
555
570
remaining_buf. len ( ) as u32 ,
556
571
& mut bytes_read,
@@ -593,11 +608,18 @@ impl MessageReader {
593
608
} ,
594
609
Err ( winapi:: ERROR_BROKEN_PIPE ) => {
595
610
win32_trace ! ( "[$ {:?}] BROKEN_PIPE straight from ReadFile" , self . handle) ;
596
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
611
+
612
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
613
+ self . handle = async_data. handle ;
614
+ self . read_buf = async_data. buf ;
615
+
597
616
Err ( WinError :: ChannelClosed )
598
617
} ,
599
618
Err ( err) => {
600
- self . read_buf = self . async . take ( ) . unwrap ( ) . into_inner ( ) . buf ;
619
+ let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
620
+ self . handle = async_data. handle ;
621
+ self . read_buf = async_data. buf ;
622
+
601
623
Err ( WinError :: from_system ( err, "ReadFile" ) )
602
624
} ,
603
625
}
@@ -621,12 +643,13 @@ impl MessageReader {
621
643
/// between receiving the completion notification from the kernel
622
644
/// and invoking this method.
623
645
unsafe fn notify_completion ( & mut self , io_result : Result < ( ) , WinError > ) -> Result < ( ) , WinError > {
624
- win32_trace ! ( "[$ {:?}] notify_completion" , self . handle) ;
646
+ win32_trace ! ( "[$ {:?}] notify_completion" , self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle) ;
625
647
626
648
// Regardless whether the kernel reported success or error,
627
649
// it doesn't have an async read operation in flight at this point anymore.
628
650
// (And it's safe again to access the `async` data.)
629
651
let async_data = self . async . take ( ) . unwrap ( ) . into_inner ( ) ;
652
+ self . handle = async_data. handle ;
630
653
let ov = async_data. ov ;
631
654
self . read_buf = async_data. buf ;
632
655
@@ -677,7 +700,7 @@ impl MessageReader {
677
700
BlockingMode :: Blocking => winapi:: TRUE ,
678
701
BlockingMode :: Nonblocking => winapi:: FALSE ,
679
702
} ;
680
- let ok = kernel32:: GetOverlappedResult ( self . handle . as_raw ( ) ,
703
+ let ok = kernel32:: GetOverlappedResult ( self . async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ,
681
704
self . async . as_mut ( ) . unwrap ( ) . alias_mut ( ) . ov . deref_mut ( ) ,
682
705
& mut nbytes,
683
706
block) ;
@@ -1405,7 +1428,10 @@ impl OsIpcReceiverSet {
1405
1428
1406
1429
// Find the matching receiver
1407
1430
let ( reader_index, _) = self . readers . iter ( ) . enumerate ( )
1408
- . find ( |& ( _, ref reader) | reader. handle . as_raw ( ) as winapi:: ULONG_PTR == completion_key)
1431
+ . find ( |& ( _, ref reader) | {
1432
+ let raw_handle = reader. async . as_ref ( ) . unwrap ( ) . alias ( ) . handle . as_raw ( ) ;
1433
+ raw_handle as winapi:: ULONG_PTR == completion_key
1434
+ } )
1409
1435
. expect ( "Windows IPC ReceiverSet got notification for a receiver it doesn't know about" ) ;
1410
1436
1411
1437
// Remove the entry from the set for now -- we will re-add it later,
0 commit comments