From dbdaa7fc60d78bfdc1474fdb47e825653b382bbe Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Tue, 8 Mar 2022 07:48:23 -0700 Subject: [PATCH] [v9] backport 10915 (memory leak) (#10927) --- lib/srv/desktop/rdp/rdpclient/client.go | 12 +++++++++--- lib/srv/desktop/rdp/rdpclient/librdprs.h | 2 +- lib/srv/desktop/rdp/rdpclient/src/lib.rs | 7 +++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/srv/desktop/rdp/rdpclient/client.go b/lib/srv/desktop/rdp/rdpclient/client.go index e298b7ab17739..d191c768feba4 100644 --- a/lib/srv/desktop/rdp/rdpclient/client.go +++ b/lib/srv/desktop/rdp/rdpclient/client.go @@ -382,17 +382,23 @@ func (c *Client) start() { } //export handle_bitmap -func handle_bitmap(handle C.uintptr_t, cb C.CGOBitmap) C.CGOError { +func handle_bitmap(handle C.uintptr_t, cb *C.CGOBitmap) C.CGOError { return cgo.Handle(handle).Value().(*Client).handleBitmap(cb) } -func (c *Client) handleBitmap(cb C.CGOBitmap) C.CGOError { +func (c *Client) handleBitmap(cb *C.CGOBitmap) C.CGOError { // Notify the input forwarding goroutine that we're ready for input. // Input can only be sent after connection was established, which we infer // from the fact that a bitmap was sent. atomic.StoreUint32(&c.readyForInput, 1) - data := C.GoBytes(unsafe.Pointer(cb.data_ptr), C.int(cb.data_len)) + // use unsafe.Slice here instead of C.GoBytes, because unsafe.Slice + // creates a Go slice backed by data managed from Rust - it does not + // copy. This way we only need one copy into img.Pix below. + ptr := unsafe.Pointer(cb.data_ptr) + uptr := (*uint8)(ptr) + data := unsafe.Slice(uptr, C.int(cb.data_len)) + // Convert BGRA to RGBA. It's likely due to Windows using uint32 values for // pixels (ARGB) and encoding them as big endian. The image.RGBA type uses // a byte slice with 4-byte segments representing pixels (RGBA). diff --git a/lib/srv/desktop/rdp/rdpclient/librdprs.h b/lib/srv/desktop/rdp/rdpclient/librdprs.h index 49986ff8b28ca..e31462e98dc69 100644 --- a/lib/srv/desktop/rdp/rdpclient/librdprs.h +++ b/lib/srv/desktop/rdp/rdpclient/librdprs.h @@ -178,6 +178,6 @@ void free_rust_string(char *s); extern void free_go_string(char *s); -extern CGOError handle_bitmap(uintptr_t client_ref, struct CGOBitmap b); +extern CGOError handle_bitmap(uintptr_t client_ref, struct CGOBitmap *b); extern CGOError handle_remote_copy(uintptr_t client_ref, uint8_t *data, uint32_t len); diff --git a/lib/srv/desktop/rdp/rdpclient/src/lib.rs b/lib/srv/desktop/rdp/rdpclient/src/lib.rs index 46379f0bbed1b..ba8529174f411 100644 --- a/lib/srv/desktop/rdp/rdpclient/src/lib.rs +++ b/lib/srv/desktop/rdp/rdpclient/src/lib.rs @@ -458,7 +458,7 @@ fn read_rdp_output_inner(client: &Client) -> Option { .unwrap() .read(|rdp_event| match rdp_event { RdpEvent::Bitmap(bitmap) => { - let cbitmap = match CGOBitmap::try_from(bitmap) { + let mut cbitmap = match CGOBitmap::try_from(bitmap) { Ok(cb) => cb, Err(e) => { error!( @@ -469,7 +469,7 @@ fn read_rdp_output_inner(client: &Client) -> Option { } }; unsafe { - err = handle_bitmap(client_ref, cbitmap) as CGOError; + err = handle_bitmap(client_ref, &mut cbitmap) as CGOError; }; } // These should never really be sent by the server to us. @@ -696,8 +696,7 @@ unsafe fn from_cgo_error(e: CGOError) -> String { // comments. extern "C" { fn free_go_string(s: *mut c_char); - fn handle_bitmap(client_ref: usize, b: CGOBitmap) -> CGOError; - + fn handle_bitmap(client_ref: usize, b: *mut CGOBitmap) -> CGOError; fn handle_remote_copy(client_ref: usize, data: *mut u8, len: u32) -> CGOError; }