Merge changes I0ed00441,I12d46493,Ib484f701 am: 0a01830612

am: 1425641300

Change-Id: I6fbd5287542ee758c6a15fff544b12bac8205eb4
This commit is contained in:
Josh Gao 2017-09-14 20:37:14 +00:00 committed by android-build-merger
commit da20ef4684
5 changed files with 66 additions and 62 deletions

View file

@ -412,8 +412,13 @@ static void device_disconnected(libusb_device* device) {
if (it != usb_handles.end()) { if (it != usb_handles.end()) {
if (!it->second->device_handle) { if (!it->second->device_handle) {
// If the handle is null, we were never able to open the device. // If the handle is null, we were never able to open the device.
unregister_usb_transport(it->second.get());
// Temporarily release the usb handles mutex to avoid deadlock.
std::unique_ptr<usb_handle> handle = std::move(it->second);
usb_handles.erase(it); usb_handles.erase(it);
lock.unlock();
unregister_usb_transport(handle.get());
lock.lock();
} else { } else {
// Closure of the transport will erase the usb_handle. // Closure of the transport will erase the usb_handle.
} }

View file

@ -19,84 +19,83 @@
#include <stddef.h> #include <stddef.h>
#include <memory>
#include "fdevent.h" #include "fdevent.h"
struct apacket; struct apacket;
class atransport; class atransport;
/* An asocket represents one half of a connection between a local and /* An asocket represents one half of a connection between a local and
** remote entity. A local asocket is bound to a file descriptor. A * remote entity. A local asocket is bound to a file descriptor. A
** remote asocket is bound to the protocol engine. * remote asocket is bound to the protocol engine.
*/ */
struct asocket { struct asocket {
/* chain pointers for the local/remote list of /* chain pointers for the local/remote list of
** asockets that this asocket lives in * asockets that this asocket lives in
*/ */
asocket *next; asocket* next;
asocket *prev; asocket* prev;
/* the unique identifier for this asocket /* the unique identifier for this asocket
*/ */
unsigned id; unsigned id;
/* flag: set when the socket's peer has closed /* flag: set when the socket's peer has closed
** but packets are still queued for delivery * but packets are still queued for delivery
*/ */
int closing; int closing;
// flag: set when the socket failed to write, so the socket will not wait to // flag: set when the socket failed to write, so the socket will not wait to
// write packets and close directly. // write packets and close directly.
bool has_write_error; bool has_write_error;
/* flag: quit adbd when both ends close the /* flag: quit adbd when both ends close the
** local service socket * local service socket
*/ */
int exit_on_close; int exit_on_close;
/* the asocket we are connected to // the asocket we are connected to
*/ asocket* peer;
asocket *peer; /* For local asockets, the fde is used to bind
* us to our fd event system. For remote asockets
/* For local asockets, the fde is used to bind * these fields are not used.
** us to our fd event system. For remote asockets */
** these fields are not used.
*/
fdevent fde; fdevent fde;
int fd; int fd;
/* queue of apackets waiting to be written // queue of apackets waiting to be written
*/ apacket* pkt_first;
apacket *pkt_first; apacket* pkt_last;
apacket *pkt_last;
/* enqueue is called by our peer when it has data /* enqueue is called by our peer when it has data
** for us. It should return 0 if we can accept more * for us. It should return 0 if we can accept more
** data or 1 if not. If we return 1, we must call * data or 1 if not. If we return 1, we must call
** peer->ready() when we once again are ready to * peer->ready() when we once again are ready to
** receive data. * receive data.
*/ */
int (*enqueue)(asocket *s, apacket *pkt); int (*enqueue)(asocket* s, apacket* pkt);
/* ready is called by the peer when it is ready for /* ready is called by the peer when it is ready for
** us to send data via enqueue again * us to send data via enqueue again
*/ */
void (*ready)(asocket *s); void (*ready)(asocket* s);
/* shutdown is called by the peer before it goes away. /* shutdown is called by the peer before it goes away.
** the socket should not do any further calls on its peer. * the socket should not do any further calls on its peer.
** Always followed by a call to close. Optional, i.e. can be NULL. * Always followed by a call to close. Optional, i.e. can be NULL.
*/ */
void (*shutdown)(asocket *s); void (*shutdown)(asocket* s);
/* close is called by the peer when it has gone away. /* close is called by the peer when it has gone away.
** we are not allowed to make any further calls on the * we are not allowed to make any further calls on the
** peer once our close method is called. * peer once our close method is called.
*/ */
void (*close)(asocket *s); void (*close)(asocket* s);
/* A socket is bound to atransport */ /* A socket is bound to atransport */
atransport *transport; atransport* transport;
size_t get_max_payload() const; size_t get_max_payload() const;
}; };

View file

@ -96,7 +96,7 @@ void install_local_socket(asocket* s) {
} }
void remove_socket(asocket* s) { void remove_socket(asocket* s) {
// socket_list_lock should already be held std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
if (s->prev && s->next) { if (s->prev && s->next) {
s->prev->next = s->next; s->prev->next = s->next;
s->next->prev = s->prev; s->next->prev = s->prev;

View file

@ -615,15 +615,15 @@ static void remove_transport(atransport* transport) {
static void transport_unref(atransport* t) { static void transport_unref(atransport* t) {
CHECK(t != nullptr); CHECK(t != nullptr);
size_t old_refcount = t->ref_count--; std::lock_guard<std::recursive_mutex> lock(transport_lock);
CHECK_GT(old_refcount, 0u); CHECK_GT(t->ref_count, 0u);
t->ref_count--;
if (old_refcount == 1u) { if (t->ref_count == 0) {
D("transport: %s unref (kicking and closing)", t->serial); D("transport: %s unref (kicking and closing)", t->serial);
t->close(t); t->close(t);
remove_transport(t); remove_transport(t);
} else { } else {
D("transport: %s unref (count=%zu)", t->serial, old_refcount - 1); D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
} }
} }

View file

@ -64,7 +64,7 @@ class atransport {
// it's better to do this piece by piece. // it's better to do this piece by piece.
atransport(ConnectionState state = kCsOffline) atransport(ConnectionState state = kCsOffline)
: id(NextTransportId()), ref_count(0), connection_state_(state) { : id(NextTransportId()), connection_state_(state) {
transport_fde = {}; transport_fde = {};
protocol_version = A_VERSION; protocol_version = A_VERSION;
max_payload = MAX_PAYLOAD; max_payload = MAX_PAYLOAD;
@ -88,7 +88,7 @@ class atransport {
int fd = -1; int fd = -1;
int transport_socket = -1; int transport_socket = -1;
fdevent transport_fde; fdevent transport_fde;
std::atomic<size_t> ref_count; size_t ref_count = 0;
uint32_t sync_token = 0; uint32_t sync_token = 0;
bool online = false; bool online = false;
TransportType type = kTransportAny; TransportType type = kTransportAny;