@@ -144,7 +144,7 @@ struct Resolution<'a> {
144144 // Pool used for allocating `Vec<ngx_addr_t>` contents in `Res`. Read by
145145 // the callback handler.
146146 pool : & ' a Pool ,
147- // Pointer to the ngx_resolver_ctx_t.
147+ // Owned pointer to the ngx_resolver_ctx_t.
148148 ctx : Option < ResolverCtx > ,
149149}
150150
@@ -184,20 +184,33 @@ impl<'a> Resolution<'a> {
184184impl < ' a > core:: future:: Future for Resolution < ' a > {
185185 type Output = Result < Vec < ngx_addr_t , Pool > , Error > ;
186186
187- fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
188- let mut this = self . as_mut ( ) ;
189-
187+ fn poll ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
188+ // Resolution is Unpin, so we can use it as just a &mut Resolution
189+ let this: & mut Resolution = self . get_mut ( ) ;
190+ // First time a Resolution is polled, start resolution.
190191 if this. waker . is_none ( ) && this. complete . is_none ( ) {
191- let addr = core:: ptr:: from_mut ( unsafe { Pin :: into_inner_unchecked ( this. as_mut ( ) ) } ) ;
192-
193- if let Some ( ctx) = & mut this. ctx {
194- // Start name resolution using the ctx. If the name is in the dns
195- // cache, the handler may get called from this stack. Otherwise, it
196- // will be called later by nginx when it gets a dns response or a
197- // timeout.
198- ctx. data = addr. cast ( ) ;
199- ctx. resolve ( ) ?;
200- }
192+ // Because Resolution is pinned, the *mut pointer from &mut
193+ // Resolution can be safely used to reconstruct a &mut Resolution
194+ // in the handler anytime until the Future is Ready (which is
195+ // always preceeded by use of this addr in the handler) or
196+ // Resolution is dropped, which will drop the ResolverCtx as well,
197+ // cancelling any resolution for which the handler has not yet
198+ // been called.
199+ let addr = core:: ptr:: from_mut ( this) ;
200+
201+ // Start name resolution using the ctx. If the name is in the dns
202+ // cache, the handler may get called from this stack. Otherwise, it
203+ // will be called later by nginx when it gets a dns response or a
204+ // timeout.
205+ let ctx = this
206+ . ctx
207+ . as_mut ( )
208+ . expect ( "ctx is Some between Resolution construction and handler" ) ;
209+ ctx. data = addr. cast ( ) ;
210+ // Does calling the handler inside this call cause UB? We haven't
211+ // told rustc that know we have passed &mut Self to the handler by
212+ // way of the ctx.
213+ ctx. resolve ( ) ?;
201214 }
202215
203216 // The handler populates this.complete, and we consume it here:
@@ -206,9 +219,9 @@ impl<'a> core::future::Future for Resolution<'a> {
206219 None => {
207220 // If the handler has not yet fired, populate the waker field,
208221 // which the handler will consume:
209- match & mut self . waker {
222+ match & mut this . waker {
210223 None => {
211- self . waker = Some ( cx. waker ( ) . clone ( ) ) ;
224+ this . waker = Some ( cx. waker ( ) . clone ( ) ) ;
212225 }
213226 Some ( w) => w. clone_from ( cx. waker ( ) ) ,
214227 }
@@ -218,6 +231,7 @@ impl<'a> core::future::Future for Resolution<'a> {
218231 }
219232}
220233
234+ /// An owned ngx_resolver_ctx_t.
221235struct ResolverCtx ( NonNull < ngx_resolver_ctx_t > ) ;
222236
223237impl core:: ops:: Deref for ResolverCtx {
@@ -268,8 +282,8 @@ impl ResolverCtx {
268282 }
269283
270284 /// Take the results in a ctx and make an owned copy as a
271- /// Result<Vec<ngx_addr_t>, Error>, where the internals of the ngx_addr_t
272- /// are allocated on the given Pool
285+ /// Result<Vec<ngx_addr_t, Pool >, Error>, where the Vec and the internals
286+ /// of the ngx_addr_t are allocated on the given Pool
273287 pub fn into_result ( self , pool : & Pool ) -> Result < Vec < ngx_addr_t , Pool > , Error > {
274288 if let Some ( e) = NonZero :: new ( self . state ) {
275289 return Err ( Error :: Resolver (
0 commit comments