@@ -702,6 +702,21 @@ macro_rules! define_quic_handle_ctx_fn {
702702 }
703703 }
704704
705+ /// Gets the callback context without clearing it from the handle.
706+ ///
707+ /// # Safety
708+ /// Only call while closing the handle, so MsQuic will not read the
709+ /// context again after this function returns. Calling this in other
710+ /// situations can cause double frees or use-after-free.
711+ unsafe fn peek_callback_ctx( & self ) -> Option <Box <Box <$callback_type>>> {
712+ let ctx = self . get_context( ) ;
713+ if ctx. is_null( ) {
714+ None
715+ } else {
716+ Some ( Box :: from_raw( ctx as * mut Box <$callback_type>) )
717+ }
718+ }
719+
705720 /// Removes the callback context from the handle and returns it.
706721 ///
707722 /// # Safety
@@ -927,8 +942,8 @@ impl Connection {
927942
928943 fn close_inner ( & self ) {
929944 if !self . handle . is_null ( ) {
930- // get the context and drop it after handle close .
931- let ctx = unsafe { self . take_callback_ctx ( ) } ;
945+ // Keep the context alive until ConnectionClose completes, then drop it .
946+ let ctx = unsafe { self . peek_callback_ctx ( ) } ;
932947 unsafe {
933948 Api :: ffi_ref ( ) . ConnectionClose . unwrap ( ) ( self . handle ) ;
934949 }
@@ -1107,8 +1122,8 @@ impl Listener {
11071122
11081123 fn close_inner ( & self ) {
11091124 if !self . handle . is_null ( ) {
1110- // consume the context and drop it after handle close .
1111- let ctx = unsafe { self . take_callback_ctx ( ) } ;
1125+ // Keep the context alive until ListenerClose completes, then drop it .
1126+ let ctx = unsafe { self . peek_callback_ctx ( ) } ;
11121127 unsafe {
11131128 Api :: ffi_ref ( ) . ListenerClose . unwrap ( ) ( self . handle ) ;
11141129 }
@@ -1184,8 +1199,8 @@ impl Stream {
11841199
11851200 pub fn close_inner ( & self ) {
11861201 if !self . handle . is_null ( ) {
1187- // consume the context and drop it after handle close .
1188- let ctx = unsafe { self . take_callback_ctx ( ) } ;
1202+ // Keep the context alive until StreamClose completes, then drop it .
1203+ let ctx = unsafe { self . peek_callback_ctx ( ) } ;
11891204 unsafe {
11901205 Api :: ffi_ref ( ) . StreamClose . unwrap ( ) ( self . handle ) ;
11911206 }
0 commit comments