From a84c0892f12ec93048a68efc3a8ba6a817a858db Mon Sep 17 00:00:00 2001 From: Greg Zharun Date: Thu, 27 Nov 2014 14:15:19 +0200 Subject: [PATCH] [Summary] Fixed error with draining IOChannel in CrossthreadChannel on Windows. Used IOChannel for base_ui on Windows instead of workaround which used to be working instead. [Reviewed by] Paul Davis --- libs/pbd/base_ui.cc | 36 +------------------------- libs/pbd/crossthread.win.cc | 51 +++++++++++++++++++++---------------- libs/pbd/pbd/base_ui.h | 9 +------ 3 files changed, 31 insertions(+), 65 deletions(-) diff --git a/libs/pbd/base_ui.cc b/libs/pbd/base_ui.cc index 08be0b87ec..99d9fbff5b 100644 --- a/libs/pbd/base_ui.cc +++ b/libs/pbd/base_ui.cc @@ -51,15 +51,10 @@ BaseUI::BaseUI (const string& str) : m_context(MainContext::get_default()) , run_loop_thread (0) , _name (str) -#ifndef PLATFORM_WINDOWS , request_channel (true) -#endif { base_ui_instance = this; - -#ifndef PLATFORM_WINDOWS request_channel.set_receive_handler (sigc::mem_fun (*this, &BaseUI::request_handler)); -#endif /* derived class must set _ok */ } @@ -124,24 +119,6 @@ BaseUI::quit () } } -#ifdef PLATFORM_WINDOWS -gboolean -BaseUI::_request_handler (gpointer data) -{ - BaseUI* ui = static_cast(data); - return ui->request_handler (); -} - -bool -BaseUI::request_handler () -{ - DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::request_handler\n"); - handle_ui_requests (); - // keep calling indefinitely at the timeout interval - return true; -} - -#else bool BaseUI::request_handler (Glib::IOCondition ioc) { @@ -166,17 +143,12 @@ BaseUI::request_handler (Glib::IOCondition ioc) return true; } -#endif void BaseUI::signal_new_request () { DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::signal_new_request\n"); -#ifdef PLATFORM_WINDOWS - // handled in timeout, how to signal...? -#else request_channel.wakeup (); -#endif } /** @@ -186,11 +158,5 @@ void BaseUI::attach_request_source () { DEBUG_TRACE (DEBUG::EventLoop, "BaseUI::attach_request_source\n"); -#ifdef PLATFORM_WINDOWS - GSource* request_source = g_timeout_source_new(200); - g_source_set_callback (request_source, &BaseUI::_request_handler, this, NULL); - g_source_attach (request_source, m_context->gobj()); -#else - request_channel.attach (m_context); -#endif + request_channel.attach (m_context); } diff --git a/libs/pbd/crossthread.win.cc b/libs/pbd/crossthread.win.cc index 33676ecf53..7f4967fe0a 100644 --- a/libs/pbd/crossthread.win.cc +++ b/libs/pbd/crossthread.win.cc @@ -38,7 +38,7 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking) // Create Send Socket send_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); send_address.sin_family = AF_INET; - send_address.sin_addr.s_addr = INADDR_ANY; + send_address.sin_addr.s_addr = inet_addr("127.0.0.1"); send_address.sin_port = htons(0); int status = bind(send_socket, (SOCKADDR*)&send_address, sizeof(send_address)); @@ -70,14 +70,7 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking) return; } - // make the socket non-blockable if required - mode = (u_long)non_blocking; - otp_result = 0; - - otp_result = ioctlsocket(receive_socket, FIONBIO, &mode); - if (otp_result != NO_ERROR) { - std::cerr << "CrossThreadChannel::CrossThreadChannel() Receive socket cannot be set to non blocking mode with error: " << WSAGetLastError() << std::endl; - } + // recieve socket will be made non-blocking by GSource which will use it // get assigned port number for Receive Socket int recv_addr_len = sizeof(recv_address); @@ -91,18 +84,15 @@ CrossThreadChannel::CrossThreadChannel (bool non_blocking) // construct IOChannel receive_channel = g_io_channel_win32_new_socket((gint)receive_socket); - int flags = G_IO_FLAG_APPEND; - if (non_blocking) { - flags |= G_IO_FLAG_NONBLOCK; - } - - GIOStatus g_status = g_io_channel_set_flags(receive_channel, (GIOFlags)flags, - NULL); - + // set binary data type + GIOStatus g_status = g_io_channel_set_encoding (receive_channel, NULL, NULL); if (G_IO_STATUS_NORMAL != g_status ) { - std::cerr << "CrossThreadChannel::CrossThreadChannel() Cannot set IOChannel flags " << std::endl; - return; + std::cerr << "CrossThreadChannel::CrossThreadChannel() Cannot set flag for IOChannel. " << g_status << std::endl; + return; } + + // disable channel buffering + g_io_channel_set_buffered (receive_channel, false); } CrossThreadChannel::~CrossThreadChannel () @@ -132,11 +122,28 @@ CrossThreadChannel::drain () { /* flush the buffer - empty the channel from all requests */ GError *g_error = 0; - gchar* buffer; + gchar buffer[512]; gsize read = 0; - g_io_channel_read_to_end (receive_channel, &buffer, &read, &g_error); - g_free(buffer); + while (1) { + GIOStatus g_status = g_io_channel_read_chars (receive_channel, buffer, sizeof(buffer), &read, &g_error); + + if (G_IO_STATUS_AGAIN == g_status) { + break; + } + + if (G_IO_STATUS_NORMAL != g_status) { + std::cerr << "CrossThreadChannel::CrossThreadChannel() Cannot drain from read buffer! " << g_status << std::endl; + + if (g_error) { + std::cerr << "Error is Domain: " << g_error->domain << " Code: " << g_error->code << std::endl; + g_clear_error(&g_error); + } else { + std::cerr << "No error provided\n"; + } + break; + } + } } diff --git a/libs/pbd/pbd/base_ui.h b/libs/pbd/pbd/base_ui.h index ea1afbbb5a..fbee20dd64 100644 --- a/libs/pbd/pbd/base_ui.h +++ b/libs/pbd/pbd/base_ui.h @@ -93,14 +93,9 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop virtual void thread_init () {}; -#ifdef PLATFORM_WINDOWS - static gboolean _request_handler (gpointer); - bool request_handler (); -#else /** Called when there input ready on the request_channel */ bool request_handler (Glib::IOCondition); -#endif void signal_new_request (); void attach_request_source (); @@ -115,10 +110,8 @@ class LIBPBD_API BaseUI : public sigc::trackable, public PBD::EventLoop std::string _name; BaseUI* base_ui_instance; -#ifndef PLATFORM_WINDOWS CrossThreadChannel request_channel; -#endif - + static uint64_t rt_bit; int setup_request_pipe ();