From f67344b4c6c7df01dd1e9f3023fa20416103cb6a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 21 Dec 2012 05:35:26 +0000 Subject: Fix UI operation via socket. Fix crashes and deadlocks on shutdown. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4872 a436a847-0d15-0410-975c-d299462d15a1 --- src/World.cpp | 21 +++++++++++---------- src/gui/ConnectWindow.cpp | 2 +- src/ingen/main.cpp | 1 + src/server/Broadcaster.cpp | 6 ++++++ src/server/Broadcaster.hpp | 1 + src/socket/Socket.cpp | 1 - src/socket/SocketReader.cpp | 30 +++++++++++++----------------- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/World.cpp b/src/World.cpp index a7e3fc02..bcdc4d70 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -149,6 +149,14 @@ public: interface_factories.clear(); script_runners.clear(); + // Delete module objects but save pointers to libraries + typedef std::list Libs; + Libs libs; + for (Modules::iterator i = modules.begin(); i != modules.end(); ++i) { + libs.push_back(i->second->library); + delete i->second; + } + delete rdf_world; delete lv2_features; delete uris; @@ -157,16 +165,9 @@ public: lilv_world_free(lilv_world); - - for (Modules::iterator i = modules.begin(); i != modules.end(); ++i) { - // Keep a reference to the library - Glib::Module* lib = i->second->library; - - // Destroy the Ingen module - delete i->second; - - // Now all references to library code should be done, close it - delete lib; + // Close module libraries + for (Libs::iterator l = libs.begin(); l != libs.end(); ++l) { + delete *l; } } diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index 97ffe03e..7951b479 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -412,7 +412,7 @@ ConnectWindow::gtk_callback() } } } else if (_connect_stage == 2) { - _app->interface()->get(Node::root_uri()); + _app->interface()->get(Raul::URI(Node::root_uri() + "/")); if (_widgets_loaded) _progress_label->set_text(string("Requesting root graph...")); ++_connect_stage; diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index d1b08f52..4c6a5925 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -209,6 +209,7 @@ main(int argc, char** argv) if (world->engine()) world->engine()->deactivate(); + engine_interface.reset(); delete world; return 0; diff --git a/src/server/Broadcaster.cpp b/src/server/Broadcaster.cpp index ab6b16fb..6c111a1c 100644 --- a/src/server/Broadcaster.cpp +++ b/src/server/Broadcaster.cpp @@ -26,6 +26,12 @@ namespace Ingen { namespace Server { +Broadcaster::~Broadcaster() +{ + Glib::Mutex::Lock lock(_clients_mutex); + _clients.clear(); +} + /** Register a client to receive messages over the notification band. */ void diff --git a/src/server/Broadcaster.hpp b/src/server/Broadcaster.hpp index 621b6b61..34bfa728 100644 --- a/src/server/Broadcaster.hpp +++ b/src/server/Broadcaster.hpp @@ -43,6 +43,7 @@ class Broadcaster : public Interface { public: Broadcaster() : _bundle_depth(0) {} + ~Broadcaster(); void register_client(const Raul::URI& uri, SharedPtr client); bool unregister_client(const Raul::URI& uri); diff --git a/src/socket/Socket.cpp b/src/socket/Socket.cpp index d8329fef..4f3592cd 100644 --- a/src/socket/Socket.cpp +++ b/src/socket/Socket.cpp @@ -179,7 +179,6 @@ Socket::shutdown() { if (_sock != -1) { ::shutdown(_sock, SHUT_RDWR); - _sock = -1; } } diff --git a/src/socket/SocketReader.cpp b/src/socket/SocketReader.cpp index c1e8dfd3..12fb112f 100644 --- a/src/socket/SocketReader.cpp +++ b/src/socket/SocketReader.cpp @@ -45,6 +45,7 @@ SocketReader::SocketReader(Ingen::World& world, SocketReader::~SocketReader() { + _socket->shutdown(); join(); } @@ -90,6 +91,16 @@ SocketReader::_run() Sord::World* world = _world.rdf_world(); LV2_URID_Map* map = &_world.uri_map().urid_map_feature()->urid_map; + // Open socket as a FILE for reading directly with serd + FILE* f = fdopen(_socket->fd(), "r"); + if (!f) { + _world.log().error(Raul::fmt("Failed to open connection (%1%)\n") + % strerror(errno)); + // Connection gone, exit + _socket.reset(); + return; + } + // Use as base URI so e.g. will be a path SordNode* base_uri = sord_new_uri( world->c_obj(), (const uint8_t*)"ingen:root/"); @@ -116,17 +127,6 @@ SocketReader::_run() NULL); serd_env_set_base_uri(_env, sord_node_to_serd_node(base_uri)); - - // Read directly from the connection with serd - FILE* f = fdopen(_socket->fd(), "r"); - if (!f) { - _world.log().error(Raul::fmt("Failed to open connection (%1%)\n") - % strerror(errno)); - // Connection gone, exit - _socket.reset(); - return; - } - serd_reader_start_stream(reader, f, (const uint8_t*)"(socket)", false); // Make an AtomReader to call Ingen Interface methods based on Atom @@ -156,15 +156,12 @@ SocketReader::_run() // Read until the next '.' SerdStatus st = serd_reader_read_chunk(reader); - if (st == SERD_FAILURE) { + if (st == SERD_FAILURE || !_msg_node) { continue; // Read nothing, e.g. just whitespace } else if (st) { _world.log().error(Raul::fmt("Read error: %1%\n") % serd_strerror(st)); continue; - } else if (!_msg_node) { - _world.log().error("Received empty message\n"); - continue; } // Build an LV2_Atom at chunk.buf from the message @@ -185,8 +182,7 @@ SocketReader::_run() sratom_free(sratom); serd_reader_free(reader); sord_free(model); - - delete this; + _socket.reset(); } } // namespace Ingen -- cgit v1.2.1