summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMilan Plzik <milan.plzik@streamunlimited.com>2015-02-20 10:27:32 +0100
committerJens Georg <mail@jensge.org>2015-03-16 22:35:07 +0100
commit44b0b299e296a392c4a10aba8492b0b512565248 (patch)
treee89c2bcc21401a9251cd2856262d3c7c8e9b5ef0 /src
parent8a0a0b1002fe6d2b67d4f2b1e1bd940de4f6f360 (diff)
downloadrygel-44b0b299e296a392c4a10aba8492b0b512565248.tar.gz
renderer: Do not capture 'this' pointer in lambdas.
In Vala, 'this' pointer is captures in lambdas by default. This causes issues with a buggy C code, which depends on the order of object destruction (e.g. AVTransport is destroyed much later than the rest of services, causing it to use already-freed objects). Signed-off-by: Milan Plzik <milan.plzik@streamunlimited.com>
Diffstat (limited to 'src')
-rw-r--r--src/librygel-renderer/rygel-av-transport.vala50
1 files changed, 43 insertions, 7 deletions
diff --git a/src/librygel-renderer/rygel-av-transport.vala b/src/librygel-renderer/rygel-av-transport.vala
index 8a13d538..5fcd819f 100644
--- a/src/librygel-renderer/rygel-av-transport.vala
+++ b/src/librygel-renderer/rygel-av-transport.vala
@@ -793,6 +793,25 @@ internal class Rygel.AVTransport : Service {
bool head_faked;
+ // HACK ALERT: This work around vala's feature of capturing 'this' pointer
+ // for all lambdas introduced in a class instance, even if 'this' is never
+ // used. Captured 'this' extends lifetime of an AVTransport instance beyond
+ // time expected by GUPnP. Due to GUPnP not using weak pointers at some
+ // places (e.g. xmlNode property of GUPnPServiceInfo), a crash happens when
+ // AVTransport is freed.
+ private static void setup_check_resource_callback (AVTransport instance, Soup.Message message) {
+ var weakme = WeakRef (instance);
+ var weakmsg = WeakRef (message);
+ message.got_headers.connect( () => {
+ Rygel.AVTransport? me = (Rygel.AVTransport?)weakme.get();
+ Soup.Message? msg = (Soup.Message?)weakmsg.get();
+ if (me == null || msg == null)
+ return;
+ me.head_faked = true;
+ me.session.cancel_message (msg, msg.status_code);
+ });
+ }
+
private void check_resource (Soup.Message msg,
string _uri,
string _metadata,
@@ -810,10 +829,7 @@ internal class Rygel.AVTransport : Service {
// Fake HEAD request by cancelling the message after the headers
// were received, then restart the message
- msg.got_headers.connect ((msg) => {
- this.head_faked = true;
- this.session.cancel_message (msg, msg.status_code);
- });
+ setup_check_resource_callback (this, msg);
this.session.queue_message (msg, null);
@@ -856,6 +872,27 @@ internal class Rygel.AVTransport : Service {
}
}
+ // HACK ALERT: This work around vala's feature of capturing 'this' pointer
+ // for all lambdas introduced in a class instance, even if 'this' is never
+ // used. Captured 'this' extends lifetime of an AVTransport instance beyond
+ // time expected by GUPnP. Due to GUPnP not using weak pointers at some
+ // places (e.g. xmlNode property of GUPnPServiceInfo), a crash happens when
+ // AVTransport is freed.
+ private static void setup_handle_new_transport_uri_callback(AVTransport instance,
+ Message message, string uri, string metadata, GUPnP.ServiceAction action) {
+ var weakme = WeakRef(instance);
+ var weakmsg = WeakRef(message);
+ //var weakact = WeakRef(action);
+ message.finished.connect( () => {
+ Rygel.AVTransport? me = (Rygel.AVTransport?)weakme.get();
+ Soup.Message? msg = (Soup.Message?)weakmsg.get();
+ //GUPnP.ServiceAction? act = (GUPnP.ServiceAction?)weakact.get();
+ if (me == null || msg == null)
+ return;
+ me.check_resource (msg, uri, metadata, action);
+ });
+ }
+
private void handle_new_transport_uri (ServiceAction action,
string uri,
string metadata) {
@@ -865,9 +902,8 @@ internal class Rygel.AVTransport : Service {
"1");
message.request_headers.append ("Connection", "close");
this.head_faked = false;
- message.finished.connect ((msg) => {
- this.check_resource (msg, uri, metadata, action);
- });
+ setup_handle_new_transport_uri_callback(this, message, uri,
+ metadata, action);
this.session.queue_message (message, null);
} else {