Skip to content

Commit be73963

Browse files
committed
fix(ffi): multiple memory leaks are present in different areas of the ffi bridge
1 parent 23cef26 commit be73963

19 files changed

Lines changed: 273 additions & 166 deletions

‎crates/ui/ffi/src/apis/connections.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ use mizer_api::Message;
99
use mizer_devices::DeviceManager;
1010
use mizer_gamepads::{Axis, Button, GamepadRef, GamepadState};
1111

12-
use crate::types::{Array, FFIFromPointer};
12+
use crate::types::{drop_pointer, Array, FFIFromPointer};
1313

1414
pub struct GamepadConnectionRef(pub GamepadRef);
15+
// No drop method for this pointer as it is kept open for the whole runtime of the ui
1516
pub struct ConnectionsRef(pub DeviceManager);
1617

1718
#[no_mangle]
@@ -116,3 +117,8 @@ bitflags! {
116117
const LEFT = 0b1000;
117118
}
118119
}
120+
121+
#[no_mangle]
122+
pub extern "C" fn drop_gamepad_pointer(pointer: *const GamepadConnectionRef) {
123+
drop_pointer(pointer)
124+
}

‎crates/ui/ffi/src/apis/fixture.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::apis::programmer::{FFIColorValue, FFIFixtureId};
2-
use crate::types::{drop_pointer, Array, FFIFromPointer};
2+
use crate::types::{drop_array, drop_pointer, Array, FFIFromPointer};
33
use mizer_fixtures::{FixtureId, FixtureState, FixtureStates};
44
use std::sync::Arc;
55

@@ -61,6 +61,11 @@ pub extern "C" fn drop_fixture_pointer(ptr: *const FixturesRef) {
6161
drop_pointer(ptr);
6262
}
6363

64+
#[no_mangle]
65+
pub extern "C" fn drop_fixture_states(fixture_states: FFIFixtureStates) {
66+
drop_array(fixture_states.fixture_values);
67+
}
68+
6469
#[derive(Default)]
6570
#[repr(C)]
6671
pub struct FFIFixtureState {

‎crates/ui/ffi/src/apis/layout.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::apis::transport::Timecode;
2-
use crate::types::{drop_pointer, Array, FFIFromPointer};
2+
use crate::types::{drop_array, drop_pointer, Array, FFIFromPointer};
33
use mizer_node::NodePath;
44
use mizer_runtime::LayoutsView;
55
use parking_lot::Mutex;
@@ -171,6 +171,11 @@ pub extern "C" fn drop_layout_pointer(ptr: *const LayoutRef) {
171171
drop_pointer(ptr);
172172
}
173173

174+
#[no_mangle]
175+
pub extern "C" fn drop_step_sequencer_value(value: FFIStepSequencerValue) {
176+
drop_array(value.value);
177+
}
178+
174179
#[derive(Default)]
175180
#[repr(C)]
176181
pub struct FFIControlColor {

‎crates/ui/ffi/src/apis/mod.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::types::{drop_array, Array};
2+
13
pub mod connections;
24
pub mod fixture;
35
pub mod layout;
@@ -8,3 +10,13 @@ pub mod sequencer;
810
pub mod status;
911
pub mod timecode;
1012
pub mod transport;
13+
14+
#[no_mangle]
15+
pub extern "C" fn drop_byte_array(array: Array<u8>) {
16+
drop_array(array)
17+
}
18+
19+
#[no_mangle]
20+
pub extern "C" fn drop_double_array(array: Array<f64>) {
21+
drop_array(array)
22+
}

‎crates/ui/ffi/src/apis/node_history.rs‎

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,46 @@
1-
use std::ffi::c_char;
1+
use std::ffi::{c_char, CString};
22
use std::sync::Arc;
33

4-
use parking_lot::Mutex;
5-
64
use mizer_runtime::NodePreviewRef;
75
use mizer_util::StructuredData;
86

97
use crate::apis::programmer::FFIColorValue;
108
use crate::apis::transport::Timecode;
11-
use crate::pointer_inventory::PointerInventory;
129
use crate::types::{drop_pointer, Array, FFIFromPointer};
1310

1411
pub struct NodeHistory {
1512
preview_ref: NodePreviewRef,
16-
pointer_inventory: Mutex<PointerInventory>,
1713
}
1814

1915
impl NodeHistory {
2016
pub fn new(preview_ref: NodePreviewRef) -> Self {
2117
Self {
2218
preview_ref,
23-
pointer_inventory: Default::default(),
2419
}
2520
}
2621

27-
// TODO: This should probably drop old inventory after 2 generations
2822
fn convert(&self, data: StructuredData) -> FFIStructuredData {
29-
let mut inventory = self.pointer_inventory.lock();
30-
convert_with_inventory(data, &mut inventory)
31-
}
32-
}
33-
34-
fn convert_with_inventory(
35-
data: StructuredData,
36-
inventory: &mut PointerInventory,
37-
) -> FFIStructuredData {
38-
match data {
39-
StructuredData::Boolean(bool) => FFIStructuredData::boolean(bool),
40-
StructuredData::Float(float) => FFIStructuredData::float(float),
41-
StructuredData::Int(int) => FFIStructuredData::int(int),
42-
StructuredData::Text(text) => FFIStructuredData::text(inventory.allocate_string(text)),
43-
StructuredData::Array(array) => FFIStructuredData::array(
44-
array
45-
.into_iter()
46-
.map(|item| convert_with_inventory(item, inventory))
47-
.collect(),
48-
),
49-
StructuredData::Object(map) => FFIStructuredData::object(
50-
map.into_iter()
51-
.map(|(key, value)| FFIStructuredDataObjectEntry {
52-
key: inventory.allocate_string(key),
53-
value: convert_with_inventory(value, inventory),
54-
})
55-
.collect(),
56-
),
57-
StructuredData::Null => FFIStructuredData::null(),
23+
match data {
24+
StructuredData::Boolean(bool) => FFIStructuredData::boolean(bool),
25+
StructuredData::Float(float) => FFIStructuredData::float(float),
26+
StructuredData::Int(int) => FFIStructuredData::int(int),
27+
StructuredData::Text(text) => FFIStructuredData::text(CString::new(text).unwrap_or_default().into_raw()),
28+
StructuredData::Array(array) => FFIStructuredData::array(
29+
array
30+
.into_iter()
31+
.map(|item| self.convert(item))
32+
.collect(),
33+
),
34+
StructuredData::Object(map) => FFIStructuredData::object(
35+
map.into_iter()
36+
.map(|(key, value)| FFIStructuredDataObjectEntry {
37+
key: CString::new(key).unwrap_or_default().into_raw(),
38+
value: self.convert(value),
39+
})
40+
.collect(),
41+
),
42+
StructuredData::Null => FFIStructuredData::null(),
43+
}
5844
}
5945
}
6046

@@ -66,7 +52,7 @@ pub struct FFIStructuredData {
6652
}
6753

6854
impl FFIStructuredData {
69-
fn text(text: *const c_char) -> Self {
55+
fn text(text: *mut c_char) -> Self {
7056
Self {
7157
r#type: FFIStructuredDataType::Text,
7258
value: FFIStructuredDataValue { text },
@@ -118,6 +104,30 @@ impl FFIStructuredData {
118104
value: FFIStructuredDataValue { null: () },
119105
}
120106
}
107+
108+
pub(crate) fn as_array(&self) -> Option<Array<FFIStructuredData>> {
109+
if let FFIStructuredDataType::Array = self.r#type {
110+
Some(unsafe { self.value.array })
111+
} else {
112+
None
113+
}
114+
}
115+
116+
pub(crate) fn as_object(&self) -> Option<Array<FFIStructuredDataObjectEntry>> {
117+
if let FFIStructuredDataType::Object = self.r#type {
118+
Some(unsafe { self.value.object })
119+
} else {
120+
None
121+
}
122+
}
123+
124+
pub(crate) fn as_text(&self) -> Option<CString> {
125+
if let FFIStructuredDataType::Text = self.r#type {
126+
Some(unsafe { CString::from_raw(self.value.text) })
127+
} else {
128+
None
129+
}
130+
}
121131
}
122132

123133
#[derive(Clone, Copy)]
@@ -135,7 +145,7 @@ pub enum FFIStructuredDataType {
135145
#[derive(Clone, Copy)]
136146
#[repr(C)]
137147
pub union FFIStructuredDataValue {
138-
pub text: *const c_char,
148+
pub text: *mut c_char,
139149
pub floating_point: f64,
140150
pub integer: i64,
141151
pub boolean: u8,
@@ -147,7 +157,7 @@ pub union FFIStructuredDataValue {
147157
#[derive(Clone, Copy)]
148158
#[repr(C)]
149159
pub struct FFIStructuredDataObjectEntry {
150-
pub key: *const c_char,
160+
pub key: *mut c_char,
151161
pub value: FFIStructuredData,
152162
}
153163

@@ -215,3 +225,22 @@ pub extern "C" fn read_node_multi_preview(ptr: *const NodeHistory) -> Array<f64>
215225

216226
values.into()
217227
}
228+
229+
#[no_mangle]
230+
pub extern "C" fn drop_structured_data(data: FFIStructuredData) {
231+
if let Some(array) = data.as_array() {
232+
let vec = array.into_vec();
233+
for item in vec {
234+
drop_structured_data(item);
235+
}
236+
}else if let Some(object) = data.as_object() {
237+
let vec = object.into_vec();
238+
for item in vec {
239+
let key = unsafe { CString::from_raw(item.key) };
240+
drop(key);
241+
drop_structured_data(item.value);
242+
}
243+
}else if let Some(text) = data.as_text() {
244+
drop(text)
245+
}
246+
}

‎crates/ui/ffi/src/apis/nodes.rs‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,26 @@
1-
use crate::pointer_inventory::PointerInventory;
21
use crate::types::{drop_pointer, Array, FFIFromPointer};
32
use mizer_runtime::NodeMetadataRef;
4-
use parking_lot::Mutex;
5-
use std::ffi::c_char;
3+
use std::ffi::{c_char, CString};
64
use std::sync::Arc;
75

86
pub struct NodesRef {
97
metadata_ref: NodeMetadataRef,
10-
pointer_inventory: Mutex<PointerInventory>,
118
}
129

1310
impl NodesRef {
1411
pub fn new(metadata_ref: NodeMetadataRef) -> Self {
1512
Self {
1613
metadata_ref,
17-
pointer_inventory: Default::default(),
1814
}
1915
}
2016

2117
fn get_port_metadata<B: FromIterator<FFINodePortMetadata>>(&self) -> B {
22-
let mut pointer_inventory = self.pointer_inventory.lock();
2318
let data = self.metadata_ref.get_all_port_metadata();
2419

2520
data.into_iter()
2621
.map(|(path, port, metadata)| FFINodePortMetadata {
27-
node_path: pointer_inventory.allocate_string(path.to_string()),
28-
port_id: pointer_inventory.allocate_string(port.to_string()),
22+
node_path: CString::new(path.to_string()).unwrap_or_default().into_raw(),
23+
port_id: CString::new(port.to_string()).unwrap_or_default().into_raw(),
2924
pushed_value: metadata.pushed_value.into(),
3025
})
3126
.collect()
@@ -48,9 +43,20 @@ pub extern "C" fn drop_nodes_pointer(ptr: *const NodesRef) {
4843
drop_pointer(ptr);
4944
}
5045

46+
#[no_mangle]
47+
pub extern "C" fn drop_node_port_metadata(metadata: Array<FFINodePortMetadata>) {
48+
let vec = metadata.into_vec();
49+
for metadata in vec {
50+
unsafe {
51+
let _ = CString::from_raw(metadata.node_path);
52+
let _ = CString::from_raw(metadata.port_id);
53+
}
54+
}
55+
}
56+
5157
#[repr(C)]
5258
pub struct FFINodePortMetadata {
53-
pub node_path: *const c_char,
54-
pub port_id: *const c_char,
59+
pub node_path: *mut c_char,
60+
pub port_id: *mut c_char,
5561
pub pushed_value: u8,
5662
}

0 commit comments

Comments
 (0)