Bug 1371319 - null out pulse pointers on destruction. r=kinetik
authorDan Glastonbury <dan.glastonbury@gmail.com>
Fri, 09 Jun 2017 10:33:17 +1000
changeset 363112 3db546295a0a2d999e57b4879eee6ad25bc0f277
parent 363111 0dd4c63082dd9eaf9d0800a34eb575e05c8627fc
child 363113 45dfceacb9e8d53b7633e27c5cb458e103e3e85b
push id31994
push usercbook@mozilla.com
push dateFri, 09 Jun 2017 10:56:24 +0000
treeherdermozilla-central@7c9d96bbc400 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1371319
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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)) {