Skip to content

Commit

Permalink
Fix memleaks related to un-freed mmal objs
Browse files Browse the repository at this point in the history
I've been using rascam in a long-lived process that periodically creates
and drops a SimpleCamera (that has an encapsulated SeriousCamera)
periodically or on demand. The process mainly hosts an actix-web
HttpServer and periodically saves an image from the raspberry pi camera,
or serves a live feed from it through the front-end.

Eventually, creating SimpleCamera fails with the following error
message:

    mmal: mmal_vc_component_create: failed to create component 'vc.null_sink' (1:ENOMEM)
    mmal: mmal_component_create_core: could not create component 'vc.null_sink' (1)
    Failed to activate SimpleCamera: MMAL error: Unable to create null sink for preview Status: ENOMEM

It seems that rascam has a memory leak in GPU memory. Upon examination,
I've discovered some pointers to mmal objects created with mmal_*_create
that were never freed with mmal_*_destroy.

This commit addresses this issue by cleaning up mmal objects which
should prevent (or at least reduce) GPU memory leaks.

Note that I've been checking the GPU memory of a Raspberry Pi 3B with
the following commands:

    vcgencmd get_mem malloc
    vcgencmd get_mem reloc

After applying this commit, the periodic usage of SimpleCamera appears
to not leak the GPU memory.

Signed-off-by: Stephen Seo <seo.disparate@gmail.com>
  • Loading branch information
Stephen-Seo committed Sep 27, 2021
1 parent 06bef56 commit 6d96923
Showing 1 changed file with 33 additions and 5 deletions.
38 changes: 33 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub struct SeriousCamera {
connection_created: bool,

preview: Option<NonNull<ffi::MMAL_COMPONENT_T>>,
preview_created: bool,
preview_connection: Option<NonNull<ffi::MMAL_CONNECTION_T>>,

use_encoder: bool,
}
Expand Down Expand Up @@ -201,8 +201,8 @@ impl SeriousCamera {
encoder: None,
connection_created: false,
connection: None,
preview_created: false,
preview: None,
preview_connection: None,
use_encoder: false,
})
}
Expand Down Expand Up @@ -718,7 +718,6 @@ impl SeriousCamera {
MMAL_STATUS_T::MMAL_SUCCESS => {
let preview_ptr: *mut ffi::MMAL_COMPONENT_T = preview_ptr.assume_init();
self.preview = Some(NonNull::new(&mut *preview_ptr).unwrap());
self.preview_created = true;
Ok(())
}
s => Err(MmalError::with_status(
Expand Down Expand Up @@ -748,10 +747,11 @@ impl SeriousCamera {
ffi::MMAL_CONNECTION_FLAG_TUNNELLING
| ffi::MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT,
);

let connection_ptr: *mut ffi::MMAL_CONNECTION_T = connection_ptr.assume_init();
match status {
MMAL_STATUS_T::MMAL_SUCCESS => {
// self.preview = Unique::new(&mut *preview_ptr);
// self.preview_created = true;
self.preview_connection = Some(NonNull::new(connection_ptr).unwrap());
Ok(())
}
s => Err(
Expand Down Expand Up @@ -1090,6 +1090,34 @@ impl Drop for SeriousCamera {
#[cfg(feature = "debug")]
println!("port disabled");
}
if self.preview_connection.is_some() {
ffi::mmal_connection_disable(self.preview_connection.unwrap().as_ptr());
ffi::mmal_connection_destroy(self.preview_connection.unwrap().as_ptr());
#[cfg(feature = "debug")]
println!("preview connection destroyed");
}
if self.preview.is_some() {
ffi::mmal_component_disable(self.preview.unwrap().as_ptr());
ffi::mmal_component_destroy(self.preview.unwrap().as_ptr());
#[cfg(feature = "debug")]
println!("preview destroyed");
}
if self.pool.is_some() {
let port_ptr = if self.use_encoder {
let output = self.encoder.unwrap().as_ref().output;
*(output.offset(0) as *mut *mut ffi::MMAL_PORT_T)
} else {
let output = self.camera.as_ref().output;
*(output.offset(MMAL_CAMERA_CAPTURE_PORT) as *mut *mut ffi::MMAL_PORT_T)
};
let port_disable_result = ffi::mmal_port_disable(port_ptr);
if port_disable_result != MMAL_STATUS_T::MMAL_SUCCESS {
println!("Failed to disable port on SeriousCamera::drop()");
}
ffi::mmal_port_pool_destroy(port_ptr, self.pool.unwrap().as_ptr());
#[cfg(feature = "debug")]
println!("pool destroyed");
}

ffi::mmal_component_destroy(self.camera.as_ptr());
#[cfg(feature = "debug")]
Expand Down

0 comments on commit 6d96923

Please sign in to comment.