Bug 1371319 - null out pulse pointers on destruction. r?kinetik draft
authorDan Glastonbury <dan.glastonbury@gmail.com>
Fri, 09 Jun 2017 10:33:17 +1000
changeset 591370 21023701ab2e551ef065bf06587741ae45094004
parent 591094 e61060be36424240058f8bef4c5597f401bc8b7e
child 632497 da71c9d5d03f37c5ce641f3aa6b4e5a096e1362a
push id63035
push userbmo:dglastonbury@mozilla.com
push dateFri, 09 Jun 2017 00:35:51 +0000
reviewerskinetik
bugs1371319
milestone55.0a1
Bug 1371319 - null out pulse pointers on destruction. r?kinetik To avoid a double freeing of pa_context and pa_threaded_mainloop on error, null out pointers once the object is freed. Added assertions that pointer are null after destroy()'ing. MozReview-Commit-ID: 1Ycmkrc2kWe
media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
--- a/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
@@ -150,23 +150,26 @@ impl Context {
         // Return the result.
         Ok(ctx)
     }
 
     pub fn destroy(&mut self) {
         if !self.context.is_null() {
             unsafe { self.pulse_context_destroy() };
         }
+        assert!(self.context.is_null());
 
         if !self.mainloop.is_null() {
             unsafe {
                 pa_threaded_mainloop_stop(self.mainloop);
                 pa_threaded_mainloop_free(self.mainloop);
+                self.mainloop = ptr::null_mut();
             }
         }
+        assert!(self.mainloop.is_null());
     }
 
     pub fn new_stream(&mut self,
                       stream_name: *const c_char,
                       input_device: cubeb::DeviceId,
                       input_stream_params: Option<cubeb::StreamParams>,
                       output_device: cubeb::DeviceId,
                       output_stream_params: Option<cubeb::StreamParams>,
@@ -394,17 +397,17 @@ impl Context {
             pa_context_set_state_callback(self.context, Some(error_state), self as *mut _ as *mut _);
 
             pa_threaded_mainloop_lock(self.mainloop);
             pa_context_connect(self.context, ptr::null(), 0, ptr::null());
 
             if !self.wait_until_context_ready() {
                 pa_threaded_mainloop_unlock(self.mainloop);
                 self.pulse_context_destroy();
-                self.context = ptr::null_mut();
+                assert!(self.context.is_null());
                 return cubeb::ERROR;
             }
 
             pa_threaded_mainloop_unlock(self.mainloop);
         }
 
         let version_str = unsafe { CStr::from_ptr(pa_get_library_version()) };
         if let Ok(version) = semver::Version::parse(version_str.to_string_lossy().as_ref()) {
@@ -427,16 +430,17 @@ impl Context {
         let o = pa_context_drain(self.context, Some(drain_complete), self.mainloop as *mut _);
         if !o.is_null() {
             self.operation_wait(ptr::null_mut(), o);
             pa_operation_unref(o);
         }
         pa_context_set_state_callback(self.context, None, ptr::null_mut());
         pa_context_disconnect(self.context);
         pa_context_unref(self.context);
+        self.context = ptr::null_mut();
         pa_threaded_mainloop_unlock(self.mainloop);
     }
 
     pub fn operation_wait(&self, stream: *mut pa_stream, o: *mut pa_operation) -> bool {
         unsafe {
             while pa_operation_get_state(o) == PA_OPERATION_RUNNING {
                 pa_threaded_mainloop_wait(self.mainloop);
                 if !PA_CONTEXT_IS_GOOD(pa_context_get_state(self.context)) {