Commit 435cbb1e authored by Frediano Ziglio's avatar Frediano Ziglio

cursor-updater: Encapsulate memory management into smart pointers

Mixing exception and raw pointers can easily lead to memory leaks.
Use smart pointers to avoid it.
Signed-off-by: Frediano Ziglio's avatarFrediano Ziglio <fziglio@redhat.com>
Acked-by: Snir Sheriber's avatarSnir Sheriber <ssheribe@redhat.com>
parent 8155cb55
...@@ -66,23 +66,22 @@ public: ...@@ -66,23 +66,22 @@ public:
} }
}; };
CursorUpdater::CursorUpdater(StreamPort *stream_port) : stream_port(stream_port) CursorUpdater::CursorUpdater(StreamPort *stream_port) :
stream_port(stream_port),
con(xcb_connect(nullptr, nullptr))
{ {
con = xcb_connect(nullptr, nullptr); if (xcb_connection_has_error(con.get())) {
if (xcb_connection_has_error(con)) {
throw Error("Failed to initiate connection to X"); throw Error("Failed to initiate connection to X");
} }
xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(con)).data; xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(con.get())).data;
if (!screen) { if (!screen) {
xcb_disconnect(con);
throw Error("Cannot get XCB screen"); throw Error("Cannot get XCB screen");
} }
// init xfixes // init xfixes
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(con, &xcb_xfixes_id); const xcb_query_extension_reply_t *reply = xcb_get_extension_data(con.get(), &xcb_xfixes_id);
if (!reply || !reply->present) { if (!reply || !reply->present) {
xcb_disconnect(con);
throw Error("Get xfixes extension failed"); throw Error("Get xfixes extension failed");
} }
xfixes_event_base = reply->first_event; xfixes_event_base = reply->first_event;
...@@ -91,19 +90,21 @@ CursorUpdater::CursorUpdater(StreamPort *stream_port) : stream_port(stream_port) ...@@ -91,19 +90,21 @@ CursorUpdater::CursorUpdater(StreamPort *stream_port) : stream_port(stream_port)
xcb_xfixes_query_version_reply_t *xfixes_query_reply; xcb_xfixes_query_version_reply_t *xfixes_query_reply;
xcb_generic_error_t *error = 0; xcb_generic_error_t *error = 0;
xfixes_query_cookie = xcb_xfixes_query_version(con, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); xfixes_query_cookie = xcb_xfixes_query_version(con.get(), XCB_XFIXES_MAJOR_VERSION,
xfixes_query_reply = xcb_xfixes_query_version_reply(con, xfixes_query_cookie, &error); XCB_XFIXES_MINOR_VERSION);
xfixes_query_reply = xcb_xfixes_query_version_reply(con.get(), xfixes_query_cookie, &error);
if (!xfixes_query_reply || error) { if (!xfixes_query_reply || error) {
free(xfixes_query_reply);
free(error); free(error);
xcb_disconnect(con);
throw Error("Query xfixes extension failed"); throw Error("Query xfixes extension failed");
} }
free(xfixes_query_reply); free(xfixes_query_reply);
// register to cursor events // register to cursor events
xcb_xfixes_select_cursor_input(con ,screen->root , XCB_XFIXES_CURSOR_NOTIFY_MASK_DISPLAY_CURSOR); xcb_xfixes_select_cursor_input(con.get(), screen->root,
XCB_XFIXES_CURSOR_NOTIFY_MASK_DISPLAY_CURSOR);
xcb_flush(con); xcb_flush(con.get());
} }
void CursorUpdater::operator()() void CursorUpdater::operator()()
...@@ -112,19 +113,18 @@ void CursorUpdater::operator()() ...@@ -112,19 +113,18 @@ void CursorUpdater::operator()()
while (1) { while (1) {
try { try {
while (auto event = xcb_wait_for_event(con)) { while (auto event = xcb_wait_for_event(con.get())) {
if (event->response_type != xfixes_event_base + XCB_XFIXES_CURSOR_NOTIFY) { if (event->response_type != xfixes_event_base + XCB_XFIXES_CURSOR_NOTIFY) {
continue; continue;
} }
xcb_xfixes_get_cursor_image_cookie_t cookie; xcb_xfixes_get_cursor_image_cookie_t cookie;
xcb_xfixes_get_cursor_image_reply_t* cursor_reply;
cookie = xcb_xfixes_get_cursor_image(con); cookie = xcb_xfixes_get_cursor_image(con.get());
cursor_reply = xcb_xfixes_get_cursor_image_reply(con, cookie, nullptr); xcb_xfixes_get_cursor_image_reply_uptr
cursor_reply(xcb_xfixes_get_cursor_image_reply(con.get(), cookie, nullptr));
if (cursor_reply->cursor_serial == last_serial) { if (cursor_reply->cursor_serial == last_serial) {
free(cursor_reply);
continue; continue;
} }
...@@ -132,17 +132,18 @@ void CursorUpdater::operator()() ...@@ -132,17 +132,18 @@ void CursorUpdater::operator()()
cursor_reply->height > STREAM_MSG_CURSOR_SET_MAX_HEIGHT) { cursor_reply->height > STREAM_MSG_CURSOR_SET_MAX_HEIGHT) {
::syslog(LOG_WARNING, "cursor updater thread: ignoring cursor: too big %ux%u", ::syslog(LOG_WARNING, "cursor updater thread: ignoring cursor: too big %ux%u",
cursor_reply->width, cursor_reply->height); cursor_reply->width, cursor_reply->height);
free(cursor_reply);
continue; continue;
} }
last_serial = cursor_reply->cursor_serial; last_serial = cursor_reply->cursor_serial;
// the X11 cursor data may be in a wrong format, copy them to an uint32_t array // the X11 cursor data may be in a wrong format, copy them to an uint32_t array
size_t pixcount = xcb_xfixes_get_cursor_image_cursor_image_length(cursor_reply); size_t pixcount =
xcb_xfixes_get_cursor_image_cursor_image_length(cursor_reply.get());
std::vector<uint32_t> pixels; std::vector<uint32_t> pixels;
pixels.reserve(pixcount); pixels.reserve(pixcount);
const uint32_t *reply_pixels = xcb_xfixes_get_cursor_image_cursor_image(cursor_reply); const uint32_t *reply_pixels =
xcb_xfixes_get_cursor_image_cursor_image(cursor_reply.get());
for (size_t i = 0; i < pixcount; ++i) { for (size_t i = 0; i < pixcount; ++i) {
pixels.push_back(reply_pixels[i]); pixels.push_back(reply_pixels[i]);
...@@ -150,7 +151,6 @@ void CursorUpdater::operator()() ...@@ -150,7 +151,6 @@ void CursorUpdater::operator()()
stream_port->send<CursorMessage>(cursor_reply->width, cursor_reply->height, stream_port->send<CursorMessage>(cursor_reply->width, cursor_reply->height,
cursor_reply->xhot, cursor_reply->yhot, pixels); cursor_reply->xhot, cursor_reply->yhot, pixels);
free(cursor_reply);
} }
} catch (const std::exception &e) { } catch (const std::exception &e) {
::syslog(LOG_ERR, "Error in cursor updater thread: %s", e.what()); ::syslog(LOG_ERR, "Error in cursor updater thread: %s", e.what());
......
...@@ -10,11 +10,23 @@ ...@@ -10,11 +10,23 @@
#include "stream-port.hpp" #include "stream-port.hpp"
#include <xcb/xfixes.h> #include <xcb/xfixes.h>
#include <memory>
namespace spice { namespace spice {
namespace streaming_agent { namespace streaming_agent {
#define DECLARE_T_UPTR(type, func) \
struct type##_deleter { \
void operator()(type##_t* p) \
{ \
func(p); \
} \
}; \
using type##_uptr = std::unique_ptr<type##_t, type##_deleter>;
DECLARE_T_UPTR(xcb_connection, xcb_disconnect)
DECLARE_T_UPTR(xcb_xfixes_get_cursor_image_reply, free)
class CursorUpdater class CursorUpdater
{ {
public: public:
...@@ -24,7 +36,7 @@ public: ...@@ -24,7 +36,7 @@ public:
private: private:
StreamPort *stream_port; StreamPort *stream_port;
xcb_connection_t* con; // connection to X11 xcb_connection_uptr con; // connection to X11
uint32_t xfixes_event_base; // event number for the XFixes events uint32_t xfixes_event_base; // event number for the XFixes events
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment