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.
The C Standard, subclause 7.16.1.4, paragraph 4 [ISO/IEC 9899:2011], states:
The parameter parmN is the identifier of the rightmost parameter in
the variable parameter list in the function definition (the one just
before the ...). If the parameter parmN is declared with the register
storage class, with a function or array type, or with a type that is
not compatible with the type that results after application of the
default argument promotions, the behavior is undefined.
In case a GET operation is in progress with SRM the same request id is
valid for the whole transfer otherwise it is not possible to cancel the
transfer after the first response.
This adds support for suspending/resuming GET requests GET when SRM is
active, in this case suspending the TX queue wont stop the remote
to continue sending packets, to do that SRMP header should be set to wait
so the remote should wait.
It is not safe to call g_obex_pending_req_abort directly as pending_req
can be NULL:
Invalid read of size 4
at 0x41231E: g_obex_pending_req_abort (gobex.c:693)
by 0x416A8A: g_obex_cancel_transfer (gobex-transfer.c:647)
by 0x42DEF2: obc_transfer_cancel (transfer.c:180)
by 0x43D833: process_message.isra.5 (object.c:259)
by 0x3B0701CE85: ??? (in /usr/lib64/libdbus-1.so.3.7.4)
by 0x3B0700FA30: dbus_connection_dispatch (in /usr/lib64/libdbus-1.so.3.7.4)
by 0x43A5B7: message_dispatch (mainloop.c:76)
by 0x3B03C48962: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3B03C47E05: g_main_context_dispatch (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3B03C48157: ??? (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x3B03C48559: g_main_loop_run (in /usr/lib64/libglib-2.0.so.0.3600.3)
by 0x40D53C: main (main.c:319)
Address 0x30 is not stack'd, malloc'd or (recently) free'd
This reverts commit 8a03376544.
The patch needs to be split up and the gdbus/ changes were bogus
compared to the original commit message.
Conflicts:
Makefile.am
Makefile.obexd
profiles/cyclingspeed/cyclingspeed.c
profiles/heartrate/heartrate.c
src/error.c
Instead of trying to include config.h in each file over the tree and
possibly forgetting to include it, give a "-include config.h" argument
to the compiler so it's guaranteed that a) it will be included for all
source files and b) it will be the first header included.
gdbus/ directory is left out, since it would break other projects using
it.
If callback is provided in g_obex_cancel_transfer() current complete
callback will be replaced by the new one and user will be informed
when abort completes.
This patch create a map between posix errors code and OBEX response
opcode and use it to generate a proper response in case a transfer
failed instead of always responding with internal error.
The previous approach searched the transfer pointer itself, assuming
that the transfers has not been modified if the pointer is in the list.
However the callback could have removed the transfer and registered
another one, which can eventually point to the same memory location.
This is solved by looking for the transfer id instead of the pointer.
Frequently upon receiving the first packet servers will perform some
sort of user interaction to authorize the incoming request. It's
therefore wise to use a larger timeout for this first packet on the
client side.