summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-12-21 05:35:26 +0000
committerDavid Robillard <d@drobilla.net>2012-12-21 05:35:26 +0000
commitf67344b4c6c7df01dd1e9f3023fa20416103cb6a (patch)
tree4cf79ffe63064255f0951ac35ca2c2b7f4dd7cba
parent89703f69e36514584ec5c399f4bdc8fb2cbc4036 (diff)
downloadingen-f67344b4c6c7df01dd1e9f3023fa20416103cb6a.tar.gz
ingen-f67344b4c6c7df01dd1e9f3023fa20416103cb6a.tar.bz2
ingen-f67344b4c6c7df01dd1e9f3023fa20416103cb6a.zip
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
-rw-r--r--src/World.cpp21
-rw-r--r--src/gui/ConnectWindow.cpp2
-rw-r--r--src/ingen/main.cpp1
-rw-r--r--src/server/Broadcaster.cpp6
-rw-r--r--src/server/Broadcaster.hpp1
-rw-r--r--src/socket/Socket.cpp1
-rw-r--r--src/socket/SocketReader.cpp30
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<Glib::Module*> 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<Interface> 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 <ingen:root/> as base URI so e.g. </foo/bar> 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