summaryrefslogtreecommitdiff
path: root/gobex/gobex.c
diff options
context:
space:
mode:
authorDenis Grigorev <d.grigorev@omprussia.ru>2020-06-30 16:47:31 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2020-07-01 10:49:49 -0700
commit7a35c12a6cebb56fe321dc1276117a94ec827eec (patch)
tree8788c2f01653b293dd571fad2a2b43cde017e618 /gobex/gobex.c
parent96c140c2c4b606c1461348a5b1725441dd98f084 (diff)
downloadbluez-7a35c12a6cebb56fe321dc1276117a94ec827eec.tar.gz
gobex: Fix segfault caused by interrupted transfer
When a obex transfer is interrupted by a peer in the middle, the response G_OBEX_RSP_FORBIDDEN comes and the transfer is freed in transfer_complete. However gobex is still ref'ed and gobex->io continues to be writable, so write_data() and then g_obex_abort() are called. When the abort response comes, struct obc_transfer is already freed, which leads to the crash. Backtrace : __GI___pthread_mutex_lock (mutex=0x65732f74) at pthread_mutex_lock.c:67 0xecc6eeda in dbus_connection_get_object_path_data () from libdbus-1.so.3 0x000457d4 in g_dbus_emit_property_changed_full () at gdbus/object.c:1794 0x00045868 in g_dbus_emit_property_changed () at gdbus/object.c:1832 0x000367f0 in transfer_set_status () at obexd/client/transfer.c:211 0x0003681e in transfer_set_status () at obexd/client/transfer.c:206 xfer_complete () at obexd/client/transfer.c:672 0x00022df6 in transfer_complete () at gobex/gobex-transfer.c:103 0x00022f44 in transfer_abort_response () at gobex/gobex-transfer.c:124 0x00020a0e in handle_response () at gobex/gobex.c:1128 0x00020dde in incoming_data () at gobex/gobex.c:1373 This commit introduces g_obex_drop_tx_queue(), which will be called if a transfer error detected. After the tx queue is dropped, obex shuts down gracefully.
Diffstat (limited to 'gobex/gobex.c')
-rw-r--r--gobex/gobex.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/gobex/gobex.c b/gobex/gobex.c
index 77f1aaafd..d68a85eb6 100644
--- a/gobex/gobex.c
+++ b/gobex/gobex.c
@@ -521,6 +521,16 @@ static void enable_tx(GObex *obex)
obex->write_source = g_io_add_watch(obex->io, cond, write_data, obex);
}
+void g_obex_drop_tx_queue(GObex *obex)
+{
+ struct pending_pkt *p;
+
+ g_obex_debug(G_OBEX_DEBUG_COMMAND, "");
+
+ while ((p = g_queue_pop_head(obex->tx_queue)))
+ pending_pkt_free(p);
+}
+
static gboolean g_obex_send_internal(GObex *obex, struct pending_pkt *p,
GError **err)
{