@@ -132,28 +132,38 @@ pub impl IdleWatcher {
132
132
let handle = uvll:: idle_new ( ) ;
133
133
assert ! ( handle. is_not_null( ) ) ;
134
134
assert ! ( 0 == uvll:: idle_init( loop_. native_handle( ) , handle) ) ;
135
- uvll:: set_data_for_uv_handle ( handle, null :: < ( ) > ( ) ) ;
136
- NativeHandle :: from_native_handle ( handle)
135
+ let mut watcher: IdleWatcher = NativeHandle :: from_native_handle ( handle) ;
136
+ watcher. install_watcher_data ( ) ;
137
+ return watcher
137
138
}
138
139
}
139
140
140
141
fn start ( & mut self , cb : IdleCallback ) {
142
+ {
143
+ let data = self . get_watcher_data ( ) ;
144
+ data. idle_cb = Some ( cb) ;
145
+ }
141
146
142
- self . set_callback ( cb) ;
143
147
unsafe {
144
148
assert ! ( 0 == uvll:: idle_start( self . native_handle( ) , idle_cb) )
145
149
} ;
146
150
147
151
extern fn idle_cb ( handle : * uvll:: uv_idle_t , status : c_int ) {
148
- let idle_watcher: IdleWatcher = NativeHandle :: from_native_handle ( handle) ;
149
- let cb: & IdleCallback = idle_watcher. borrow_callback ( ) ;
152
+ let mut idle_watcher: IdleWatcher = NativeHandle :: from_native_handle ( handle) ;
153
+ let data = idle_watcher. get_watcher_data ( ) ;
154
+ let cb: & IdleCallback = data. idle_cb . get_ref ( ) ;
150
155
let status = status_to_maybe_uv_error ( handle, status) ;
151
156
( * cb) ( idle_watcher, status) ;
152
157
}
153
158
}
154
159
155
160
fn stop ( & mut self ) {
156
- unsafe { assert ! ( 0 == uvll:: idle_stop( self . native_handle( ) ) ) ; }
161
+ // NB: Not resetting the Rust idl_cb to None here because `stop` is likely
162
+ // called from *within* the idle callback, which would cause a use after free
163
+
164
+ unsafe {
165
+ assert ! ( 0 == uvll:: idle_stop( self . native_handle( ) ) ) ;
166
+ }
157
167
}
158
168
159
169
fn close ( self ) {
@@ -162,7 +172,7 @@ pub impl IdleWatcher {
162
172
extern fn close_cb ( handle : * uvll:: uv_idle_t ) {
163
173
unsafe {
164
174
let mut idle_watcher: IdleWatcher = NativeHandle :: from_native_handle ( handle) ;
165
- idle_watcher. drop_callback :: < IdleCallback > ( ) ;
175
+ idle_watcher. drop_watcher_data ( ) ;
166
176
uvll:: idle_delete ( handle) ;
167
177
}
168
178
}
@@ -185,13 +195,11 @@ struct WatcherData {
185
195
connect_cb : Option < ConnectionCallback > ,
186
196
close_cb : Option < NullCallback > ,
187
197
alloc_cb : Option < AllocCallback > ,
198
+ idle_cb : Option < IdleCallback >
188
199
}
189
200
190
201
pub trait WatcherInterop {
191
202
fn event_loop ( & self ) -> Loop ;
192
- fn set_callback < CB : Callback > ( & mut self , cb : CB ) ;
193
- fn drop_callback < CB : Callback > ( & mut self ) ;
194
- fn borrow_callback < CB : Callback > ( & self ) -> & CB ;
195
203
fn install_watcher_data ( & mut self ) ;
196
204
fn get_watcher_data < ' r > ( & ' r mut self ) -> & ' r mut WatcherData ;
197
205
fn drop_watcher_data ( & mut self ) ;
@@ -207,46 +215,6 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
207
215
}
208
216
}
209
217
210
- /// Set the custom data on a handle to a callback Note: This is only
211
- /// suitable for watchers that make just one type of callback. For
212
- /// others use WatcherData
213
- pub fn set_callback < CB : Callback > ( & mut self , cb : CB ) {
214
- unsafe {
215
- self . drop_callback :: < CB > ( ) ;
216
-
217
- // XXX: Boxing the callback so it fits into a
218
- // pointer. Unfortunate extra allocation
219
- let boxed_cb = ~cb;
220
- let data = transmute :: < ~CB , * c_void > ( boxed_cb) ;
221
- uvll:: set_data_for_uv_handle ( self . native_handle ( ) , data) ;
222
- }
223
- }
224
-
225
- /// Delete a callback from a handle's custom data
226
- pub fn drop_callback < CB : Callback > ( & mut self ) {
227
- unsafe {
228
- let handle = self . native_handle ( ) ;
229
- let handle_data: * c_void = uvll:: get_data_for_uv_handle ( handle) ;
230
- if handle_data. is_not_null ( ) {
231
- // Take ownership of the callback and drop it
232
- let _cb = transmute :: < * c_void , ~CB > ( handle_data) ;
233
- // Make sure the pointer is zeroed
234
- uvll:: set_data_for_uv_handle ( self . native_handle ( ) , null :: < ( ) > ( ) ) ;
235
- }
236
- }
237
- }
238
-
239
- /// Take a pointer to the callback installed as custom data
240
- pub fn borrow_callback < CB : Callback > ( & self ) -> & CB {
241
- unsafe {
242
- let handle = self . native_handle ( ) ;
243
- let handle_data: * c_void = uvll:: get_data_for_uv_handle ( handle) ;
244
- assert ! ( handle_data. is_not_null( ) ) ;
245
- let cb = transmute :: < & * c_void , & ~CB > ( & handle_data) ;
246
- return & * * cb;
247
- }
248
- }
249
-
250
218
pub fn install_watcher_data ( & mut self ) {
251
219
unsafe {
252
220
let data = ~WatcherData {
@@ -255,6 +223,7 @@ impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
255
223
connect_cb : None ,
256
224
close_cb : None ,
257
225
alloc_cb : None ,
226
+ idle_cb : None
258
227
} ;
259
228
let data = transmute :: < ~WatcherData , * c_void > ( data) ;
260
229
uvll:: set_data_for_uv_handle ( self . native_handle ( ) , data) ;
0 commit comments