Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cea14958 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I5e56f17f,Ie3748b6c,I4e1d56a8

* changes:
  adb: switch the socket list mutex to a recursive_mutex.
  adb: clang-format sockets.cpp.
  adb: add implementations of mutex, recursive_mutex.
parents 0321476f 9b587dec
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@
#endif
ADB_MUTEX(basename_lock)
ADB_MUTEX(dirname_lock)
ADB_MUTEX(socket_list_lock)
ADB_MUTEX(transport_lock)
#if ADB_HOST
ADB_MUTEX(local_transports_lock)
+239 −268
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <unistd.h>

#include <algorithm>
#include <mutex>
#include <string>
#include <vector>

@@ -35,17 +36,16 @@

#include "adb.h"
#include "adb_io.h"
#include "sysdeps/mutex.h"
#include "transport.h"

ADB_MUTEX_DEFINE( socket_list_lock );

static void local_socket_close_locked(asocket *s);
static void local_socket_close(asocket* s);

static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
static unsigned local_socket_next_id = 1;

static asocket local_socket_list = {
    .next = &local_socket_list,
    .prev = &local_socket_list,
    .next = &local_socket_list, .prev = &local_socket_list,
};

/* the the list of currently closing local sockets.
@@ -53,62 +53,53 @@ static asocket local_socket_list = {
** write to their fd.
*/
static asocket local_socket_closing_list = {
    .next = &local_socket_closing_list,
    .prev = &local_socket_closing_list,
    .next = &local_socket_closing_list, .prev = &local_socket_closing_list,
};

// Parse the global list of sockets to find one with id |local_id|.
// If |peer_id| is not 0, also check that it is connected to a peer
// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
asocket *find_local_socket(unsigned local_id, unsigned peer_id)
{
asocket* find_local_socket(unsigned local_id, unsigned peer_id) {
    asocket* s;
    asocket* result = NULL;

    adb_mutex_lock(&socket_list_lock);
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
        if (s->id != local_id)
        if (s->id != local_id) {
            continue;
        }
        if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
            result = s;
        }
        break;
    }
    adb_mutex_unlock(&socket_list_lock);

    return result;
}

static void
insert_local_socket(asocket*  s, asocket*  list)
{
static void insert_local_socket(asocket* s, asocket* list) {
    s->next = list;
    s->prev = s->next->prev;
    s->prev->next = s;
    s->next->prev = s;
}


void install_local_socket(asocket *s)
{
    adb_mutex_lock(&socket_list_lock);
void install_local_socket(asocket* s) {
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);

    s->id = local_socket_next_id++;

    // Socket ids should never be 0.
    if (local_socket_next_id == 0)
      local_socket_next_id = 1;
    if (local_socket_next_id == 0) {
        fatal("local socket id overflow");
    }

    insert_local_socket(s, &local_socket_list);

    adb_mutex_unlock(&socket_list_lock);
}

void remove_socket(asocket *s)
{
void remove_socket(asocket* s) {
    // socket_list_lock should already be held
    if (s->prev && s->next)
    {
    if (s->prev && s->next) {
        s->prev->next = s->next;
        s->next->prev = s->prev;
        s->next = 0;
@@ -117,26 +108,23 @@ void remove_socket(asocket *s)
    }
}

void close_all_sockets(atransport *t)
{
void close_all_sockets(atransport* t) {
    asocket* s;

    /* this is a little gross, but since s->close() *will* modify
    ** the list out from under you, your options are limited.
    */
    adb_mutex_lock(&socket_list_lock);
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
restart:
    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
        if (s->transport == t || (s->peer && s->peer->transport == t)) {
            local_socket_close_locked(s);
            local_socket_close(s);
            goto restart;
        }
    }
    adb_mutex_unlock(&socket_list_lock);
}

static int local_socket_enqueue(asocket *s, apacket *p)
{
static int local_socket_enqueue(asocket* s, apacket* p) {
    D("LS(%d): enqueue %d", s->id, p->len);

    p->ptr = p->data;
@@ -190,23 +178,14 @@ enqueue:
    return 1; /* not ready (backlog) */
}

static void local_socket_ready(asocket *s)
{
static void local_socket_ready(asocket* s) {
    /* far side is ready for data, pay attention to
       readable events */
    fdevent_add(&s->fde, FDE_READ);
}

static void local_socket_close(asocket *s)
{
    adb_mutex_lock(&socket_list_lock);
    local_socket_close_locked(s);
    adb_mutex_unlock(&socket_list_lock);
}

// be sure to hold the socket list lock when calling this
static void local_socket_destroy(asocket  *s)
{
static void local_socket_destroy(asocket* s) {
    apacket *p, *n;
    int exit_on_close = s->exit_on_close;

@@ -232,27 +211,21 @@ static void local_socket_destroy(asocket *s)
    }
}


static void local_socket_close_locked(asocket *s)
{
    D("entered local_socket_close_locked. LS(%d) fd=%d", s->id, s->fd);
static void local_socket_close(asocket* s) {
    D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
    std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
    if (s->peer) {
        D("LS(%d): closing peer. peer->id=%d peer->fd=%d",
          s->id, s->peer->id, s->peer->fd);
        D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
        /* Note: it's important to call shutdown before disconnecting from
         * the peer, this ensures that remote sockets can still get the id
         * of the local socket they're connected to, to send a CLOSE()
         * protocol event. */
        if (s->peer->shutdown)
        if (s->peer->shutdown) {
            s->peer->shutdown(s->peer);
        s->peer->peer = 0;
        // tweak to avoid deadlock
        if (s->peer->close == local_socket_close) {
            local_socket_close_locked(s->peer);
        } else {
            s->peer->close(s->peer);
        }
        s->peer = 0;
        s->peer->peer = nullptr;
        s->peer->close(s->peer);
        s->peer = nullptr;
    }

    /* If we are already closing, or if there are no
@@ -276,8 +249,7 @@ static void local_socket_close_locked(asocket *s)
    CHECK_EQ(FDE_WRITE, s->fde.state & FDE_WRITE);
}

static void local_socket_event_func(int fd, unsigned ev, void* _s)
{
static void local_socket_event_func(int fd, unsigned ev, void* _s) {
    asocket* s = reinterpret_cast<asocket*>(_s);
    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)", s->id, s->fd, fd, ev);

@@ -334,7 +306,6 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
        s->peer->ready(s->peer);
    }


    if (ev & FDE_READ) {
        apacket* p = get_apacket();
        unsigned char* x = p->data;
@@ -345,8 +316,8 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)

        while (avail > 0) {
            r = adb_read(fd, x, avail);
            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu",
              s->id, s->fd, r, r < 0 ? errno : 0, avail);
            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu", s->id, s->fd, r,
              r < 0 ? errno : 0, avail);
            if (r == -1) {
                if (errno == EAGAIN) {
                    break;
@@ -361,8 +332,8 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
            is_eof = 1;
            break;
        }
        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d",
          s->id, s->fd, r, is_eof, s->fde.force_eof);
        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d", s->id, s->fd, r, is_eof,
          s->fde.force_eof);
        if ((avail == max_payload) || (s->peer == 0)) {
            put_apacket(p);
        } else {
@@ -397,8 +368,7 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
        }
        /* Don't allow a forced eof if data is still there */
        if ((s->fde.force_eof && !r) || is_eof) {
            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d",
              is_eof, r, s->fde.force_eof);
            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d", is_eof, r, s->fde.force_eof);
            s->close(s);
            return;
        }
@@ -414,10 +384,11 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
    }
}

asocket *create_local_socket(int fd)
{
asocket* create_local_socket(int fd) {
    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
    if (s == NULL) fatal("cannot allocate socket");
    if (s == NULL) {
        fatal("cannot allocate socket");
    }
    s->fd = fd;
    s->enqueue = local_socket_enqueue;
    s->ready = local_socket_ready;
@@ -430,9 +401,7 @@ asocket *create_local_socket(int fd)
    return s;
}

asocket *create_local_service_socket(const char *name,
                                     const atransport* transport)
{
asocket* create_local_service_socket(const char* name, const atransport* transport) {
#if !ADB_HOST
    if (!strcmp(name, "jdwp")) {
        return create_jdwp_service_socket();
@@ -442,20 +411,23 @@ asocket *create_local_service_socket(const char *name,
    }
#endif
    int fd = service_to_fd(name, transport);
    if(fd < 0) return 0;
    if (fd < 0) {
        return 0;
    }

    asocket* s = create_local_socket(fd);
    D("LS(%d): bound to '%s' via %d", s->id, name, fd);

#if !ADB_HOST
    char debug[PROPERTY_VALUE_MAX];
    if (!strncmp(name, "root:", 5))
    if (!strncmp(name, "root:", 5)) {
        property_get("ro.debuggable", debug, "");
    }

    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0)
        || (!strncmp(name, "unroot:", 7) && getuid() == 0)
        || !strncmp(name, "usb:", 4)
        || !strncmp(name, "tcpip:", 6)) {
    if ((!strncmp(name, "root:", 5) && getuid() != 0 && strcmp(debug, "1") == 0) ||
        (!strncmp(name, "unroot:", 7) && getuid() == 0) ||
        !strncmp(name, "usb:", 4) ||
        !strncmp(name, "tcpip:", 6)) {
        D("LS(%d): enabling exit_on_close", s->id);
        s->exit_on_close = 1;
    }
@@ -465,8 +437,7 @@ asocket *create_local_service_socket(const char *name,
}

#if ADB_HOST
static asocket *create_host_service_socket(const char *name, const char* serial)
{
static asocket* create_host_service_socket(const char* name, const char* serial) {
    asocket* s;

    s = host_service_to_socket(name, serial);
@@ -480,10 +451,8 @@ static asocket *create_host_service_socket(const char *name, const char* serial)
}
#endif /* ADB_HOST */

static int remote_socket_enqueue(asocket *s, apacket *p)
{
    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d",
      s->id, s->fd, s->peer->fd);
static int remote_socket_enqueue(asocket* s, apacket* p) {
    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
    p->msg.command = A_WRTE;
    p->msg.arg0 = s->peer->id;
    p->msg.arg1 = s->id;
@@ -492,10 +461,8 @@ static int remote_socket_enqueue(asocket *s, apacket *p)
    return 1;
}

static void remote_socket_ready(asocket *s)
{
    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d",
      s->id, s->fd, s->peer->fd);
static void remote_socket_ready(asocket* s) {
    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
    apacket* p = get_apacket();
    p->msg.command = A_OKAY;
    p->msg.arg0 = s->peer->id;
@@ -503,10 +470,9 @@ static void remote_socket_ready(asocket *s)
    send_packet(p, s->transport);
}

static void remote_socket_shutdown(asocket *s)
{
    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d",
      s->id, s->fd, s->peer?s->peer->fd:-1);
static void remote_socket_shutdown(asocket* s) {
    D("entered remote_socket_shutdown RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
      s->peer ? s->peer->fd : -1);
    apacket* p = get_apacket();
    p->msg.command = A_CLSE;
    if (s->peer) {
@@ -516,16 +482,14 @@ static void remote_socket_shutdown(asocket *s)
    send_packet(p, s->transport);
}

static void remote_socket_close(asocket *s)
{
static void remote_socket_close(asocket* s) {
    if (s->peer) {
        s->peer->peer = 0;
        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d",
          s->id, s->peer->id, s->peer->fd);
        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
        s->peer->close(s->peer);
    }
    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d",
      s->id, s->fd, s->peer?s->peer->fd:-1);
    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d", s->id, s->fd,
      s->peer ? s->peer->fd : -1);
    D("RS(%d): closed", s->id);
    free(s);
}
@@ -534,12 +498,15 @@ static void remote_socket_close(asocket *s)
// |t|. Where |id| is the socket id of the corresponding service on the other
//  side of the transport (it is allocated by the remote side and _cannot_ be 0).
// Returns a new non-NULL asocket handle.
asocket *create_remote_socket(unsigned id, atransport *t)
{
    if (id == 0) fatal("invalid remote socket id (0)");
asocket* create_remote_socket(unsigned id, atransport* t) {
    if (id == 0) {
        fatal("invalid remote socket id (0)");
    }
    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));

    if (s == NULL) fatal("cannot allocate socket");
    if (s == NULL) {
        fatal("cannot allocate socket");
    }
    s->id = id;
    s->enqueue = remote_socket_enqueue;
    s->ready = remote_socket_ready;
@@ -551,8 +518,7 @@ asocket *create_remote_socket(unsigned id, atransport *t)
    return s;
}

void connect_to_remote(asocket *s, const char *destination)
{
void connect_to_remote(asocket* s, const char* destination) {
    D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
    apacket* p = get_apacket();
    size_t len = strlen(destination) + 1;
@@ -569,11 +535,9 @@ void connect_to_remote(asocket *s, const char *destination)
    send_packet(p, s->transport);
}


/* this is used by magic sockets to rig local sockets to
   send the go-ahead message when they connect */
static void local_socket_ready_notify(asocket *s)
{
static void local_socket_ready_notify(asocket* s) {
    s->ready = local_socket_ready;
    s->shutdown = NULL;
    s->close = local_socket_close;
@@ -584,8 +548,7 @@ static void local_socket_ready_notify(asocket *s)
/* this is used by magic sockets to rig local sockets to
   send the failure message if they are closed before
   connected (to avoid closing them without a status message) */
static void local_socket_close_notify(asocket *s)
{
static void local_socket_close_notify(asocket* s) {
    s->ready = local_socket_ready;
    s->shutdown = NULL;
    s->close = local_socket_close;
@@ -593,24 +556,37 @@ static void local_socket_close_notify(asocket *s)
    s->close(s);
}

static unsigned unhex(unsigned char *s, int len)
{
static unsigned unhex(unsigned char* s, int len) {
    unsigned n = 0, c;

    while (len-- > 0) {
        switch ((c = *s++)) {
        case '0': case '1': case '2':
        case '3': case '4': case '5':
        case '6': case '7': case '8':
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                c -= '0';
                break;
        case 'a': case 'b': case 'c':
        case 'd': case 'e': case 'f':
            case 'a':
            case 'b':
            case 'c':
            case 'd':
            case 'e':
            case 'f':
                c = c - 'a' + 10;
                break;
        case 'A': case 'B': case 'C':
        case 'D': case 'E': case 'F':
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
                c = c - 'A' + 10;
                break;
            default:
@@ -673,8 +649,7 @@ char* skip_host_serial(char* service) {

#endif  // ADB_HOST

static int smart_socket_enqueue(asocket *s, apacket *p)
{
static int smart_socket_enqueue(asocket* s, apacket* p) {
    unsigned len;
#if ADB_HOST
    char* service = nullptr;
@@ -694,8 +669,7 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
            goto fail;
        }

        memcpy(s->pkt_first->data + s->pkt_first->len,
               p->data, p->len);
        memcpy(s->pkt_first->data + s->pkt_first->len, p->data, p->len);
        s->pkt_first->len += p->len;
        put_apacket(p);

@@ -703,7 +677,9 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
    }

    /* don't bother if we can't decode the length */
    if(p->len < 4) return 0;
    if (p->len < 4) {
        return 0;
    }

    len = unhex(p->data, 4);
    if ((len < 1) || (len > MAX_PAYLOAD_V1)) {
@@ -819,7 +795,6 @@ static int smart_socket_enqueue(asocket *s, apacket *p)
        goto fail;
    }


    /* instrument our peer to pass the success or fail
    ** message back once it connects or closes, then
    ** detach from it, request the connection, and
@@ -846,13 +821,11 @@ fail:
    return -1;
}

static void smart_socket_ready(asocket *s)
{
static void smart_socket_ready(asocket* s) {
    D("SS(%d): ready", s->id);
}

static void smart_socket_close(asocket *s)
{
static void smart_socket_close(asocket* s) {
    D("SS(%d): closed", s->id);
    if (s->pkt_first) {
        put_apacket(s->pkt_first);
@@ -865,8 +838,7 @@ static void smart_socket_close(asocket *s)
    free(s);
}

static asocket *create_smart_socket(void)
{
static asocket* create_smart_socket(void) {
    D("Creating smart socket");
    asocket* s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
    if (s == NULL) fatal("cannot allocate socket");
@@ -879,8 +851,7 @@ static asocket *create_smart_socket(void)
    return s;
}

void connect_to_smartsocket(asocket *s)
{
void connect_to_smartsocket(asocket* s) {
    D("Connecting to smart socket");
    asocket* ss = create_smart_socket();
    s->peer = ss;

adb/sysdeps/mutex.h

0 → 100644
+107 −0
Original line number Diff line number Diff line
#pragma once

/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#if defined(_WIN32)

#include <windows.h>

#include <android-base/macros.h>

#include "adb.h"

// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex.
// Therefore, implement our own using the Windows primitives.
// Put them directly into the std namespace, so that when they're actually available, the build
// breaks until they're removed.

#include <mutex>
namespace std {

// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class.
class recursive_mutex {
  public:
    recursive_mutex() {
        InitializeCriticalSection(&mutex_);
    }

    ~recursive_mutex() {
        DeleteCriticalSection(&mutex_);
    }

    void lock() {
        EnterCriticalSection(&mutex_);
    }

    bool try_lock() {
        return TryEnterCriticalSection(&mutex_);
    }

    void unlock() {
        LeaveCriticalSection(&mutex_);
    }

  private:
    CRITICAL_SECTION mutex_;

    DISALLOW_COPY_AND_ASSIGN(recursive_mutex);
};

class mutex {
  public:
    mutex() {
    }

    ~mutex() {
    }

    void lock() {
        mutex_.lock();
        if (++lock_count_ != 1) {
            fatal("non-recursive mutex locked reentrantly");
        }
    }

    void unlock() {
        if (--lock_count_ != 0) {
            fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_);
        }
        mutex_.unlock();
    }

    bool try_lock() {
        if (!mutex_.try_lock()) {
            return false;
        }

        if (lock_count_ != 0) {
            mutex_.unlock();
            return false;
        }

        ++lock_count_;
        return true;
    }

  private:
    recursive_mutex mutex_;
    size_t lock_count_ = 0;
};

}

#endif
+57 −0
Original line number Diff line number Diff line
@@ -244,3 +244,60 @@ TEST_F(sysdeps_poll, fd_count) {
        adb_close(fd);
    }
}

#include "sysdeps/mutex.h"
TEST(sysdeps_mutex, mutex_smoke) {
    static std::atomic<bool> finished(false);
    static std::mutex &m = *new std::mutex();
    m.lock();
    ASSERT_FALSE(m.try_lock());
    adb_thread_create([](void*) {
        ASSERT_FALSE(m.try_lock());
        m.lock();
        finished.store(true);
        adb_sleep_ms(200);
        m.unlock();
    }, nullptr);

    ASSERT_FALSE(finished.load());
    adb_sleep_ms(100);
    ASSERT_FALSE(finished.load());
    m.unlock();
    adb_sleep_ms(100);
    m.lock();
    ASSERT_TRUE(finished.load());
    m.unlock();
}

// Our implementation on Windows aborts on double lock.
#if defined(_WIN32)
TEST(sysdeps_mutex, mutex_reentrant_lock) {
    std::mutex &m = *new std::mutex();

    m.lock();
    ASSERT_FALSE(m.try_lock());
    EXPECT_DEATH(m.lock(), "non-recursive mutex locked reentrantly");
}
#endif

TEST(sysdeps_mutex, recursive_mutex_smoke) {
    static std::recursive_mutex &m = *new std::recursive_mutex();

    m.lock();
    ASSERT_TRUE(m.try_lock());
    m.unlock();

    adb_thread_create([](void*) {
        ASSERT_FALSE(m.try_lock());
        m.lock();
        adb_sleep_ms(500);
        m.unlock();
    }, nullptr);

    adb_sleep_ms(100);
    m.unlock();
    adb_sleep_ms(100);
    ASSERT_FALSE(m.try_lock());
    m.lock();
    m.unlock();
}