• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

修訂11440395e379f35069e8e39a6e3ccfa7a7bfc72f (tree)
時間2016-08-17 07:52:46
作者Josh Gao <jmgao@goog...>
Commitergitbuildkicker

Log Message

adb: switch the socket list mutex to a recursive_mutex.

sockets.cpp was branching on whether a socket close function was
local_socket_close in order to avoid a potential deadlock if the socket
list lock was held while closing a peer socket.

Bug: http://b/28347842
Change-Id: I5e56f17fa54275284787f0f1dc150d1960256ab3
(functionally a cherrypick of 903b749f + 9b587dec, with windows disabled)

Change Summary

差異

--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -200,7 +200,10 @@ endif
200200 # will violate ODR
201201 LOCAL_SHARED_LIBRARIES :=
202202
203+# Don't build the host adb on Windows (this branch should only be used for security updates.)
204+ifneq ($(HOST_OS),windows)
203205 include $(BUILD_HOST_EXECUTABLE)
206+endif
204207
205208 $(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
206209
--- a/adb/mutex_list.h
+++ b/adb/mutex_list.h
@@ -6,7 +6,6 @@
66 #ifndef ADB_MUTEX
77 #error ADB_MUTEX not defined when including this file
88 #endif
9-ADB_MUTEX(socket_list_lock)
109 ADB_MUTEX(transport_lock)
1110 #if ADB_HOST
1211 ADB_MUTEX(local_transports_lock)
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -25,18 +25,27 @@
2525 #include <string.h>
2626 #include <unistd.h>
2727
28+#include <algorithm>
29+#include <mutex>
30+#include <string>
31+#include <vector>
32+
2833 #if !ADB_HOST
2934 #include "cutils/properties.h"
3035 #endif
3136
3237 #include "adb.h"
3338 #include "adb_io.h"
39+#include "sysdeps/mutex.h"
3440 #include "transport.h"
3541
36-ADB_MUTEX_DEFINE( socket_list_lock );
42+#if !defined(__BIONIC__)
43+using std::recursive_mutex;
44+#endif
3745
38-static void local_socket_close_locked(asocket *s);
46+static void local_socket_close(asocket* s);
3947
48+static recursive_mutex& local_socket_list_lock = *new recursive_mutex();
4049 static unsigned local_socket_next_id = 1;
4150
4251 static asocket local_socket_list = {
@@ -61,7 +70,7 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id)
6170 asocket *s;
6271 asocket *result = NULL;
6372
64- adb_mutex_lock(&socket_list_lock);
73+ std::lock_guard<recursive_mutex> lock(local_socket_list_lock);
6574 for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
6675 if (s->id != local_id)
6776 continue;
@@ -70,7 +79,6 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id)
7079 }
7180 break;
7281 }
73- adb_mutex_unlock(&socket_list_lock);
7482
7583 return result;
7684 }
@@ -84,20 +92,17 @@ insert_local_socket(asocket* s, asocket* list)
8492 s->next->prev = s;
8593 }
8694
87-
88-void install_local_socket(asocket *s)
89-{
90- adb_mutex_lock(&socket_list_lock);
95+void install_local_socket(asocket* s) {
96+ std::lock_guard<recursive_mutex> lock(local_socket_list_lock);
9197
9298 s->id = local_socket_next_id++;
9399
94100 // Socket ids should never be 0.
95- if (local_socket_next_id == 0)
96- local_socket_next_id = 1;
101+ if (local_socket_next_id == 0) {
102+ fatal("local socket id overflow");
103+ }
97104
98105 insert_local_socket(s, &local_socket_list);
99-
100- adb_mutex_unlock(&socket_list_lock);
101106 }
102107
103108 void remove_socket(asocket *s)
@@ -116,19 +121,17 @@ void remove_socket(asocket *s)
116121 void close_all_sockets(atransport *t)
117122 {
118123 asocket *s;
119-
120- /* this is a little gross, but since s->close() *will* modify
121- ** the list out from under you, your options are limited.
122- */
123- adb_mutex_lock(&socket_list_lock);
124+ /* this is a little gross, but since s->close() *will* modify
125+ ** the list out from under you, your options are limited.
126+ */
127+ std::lock_guard<recursive_mutex> lock(local_socket_list_lock);
124128 restart:
125- for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
126- if(s->transport == t || (s->peer && s->peer->transport == t)) {
127- local_socket_close_locked(s);
129+ for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
130+ if (s->transport == t || (s->peer && s->peer->transport == t)) {
131+ local_socket_close(s);
128132 goto restart;
129133 }
130134 }
131- adb_mutex_unlock(&socket_list_lock);
132135 }
133136
134137 static int local_socket_enqueue(asocket *s, apacket *p)
@@ -191,13 +194,6 @@ static void local_socket_ready(asocket *s)
191194 fdevent_add(&s->fde, FDE_READ);
192195 }
193196
194-static void local_socket_close(asocket *s)
195-{
196- adb_mutex_lock(&socket_list_lock);
197- local_socket_close_locked(s);
198- adb_mutex_unlock(&socket_list_lock);
199-}
200-
201197 // be sure to hold the socket list lock when calling this
202198 static void local_socket_destroy(asocket *s)
203199 {
@@ -226,27 +222,21 @@ static void local_socket_destroy(asocket *s)
226222 }
227223 }
228224
229-
230-static void local_socket_close_locked(asocket *s)
231-{
232- D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd);
233- if(s->peer) {
234- D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
235- s->id, s->peer->id, s->peer->fd);
225+static void local_socket_close(asocket* s) {
226+ D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd);
227+ std::lock_guard<recursive_mutex> lock(local_socket_list_lock);
228+ if (s->peer) {
229+ D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
236230 /* Note: it's important to call shutdown before disconnecting from
237231 * the peer, this ensures that remote sockets can still get the id
238232 * of the local socket they're connected to, to send a CLOSE()
239233 * protocol event. */
240- if (s->peer->shutdown)
241- s->peer->shutdown(s->peer);
242- s->peer->peer = 0;
243- // tweak to avoid deadlock
244- if (s->peer->close == local_socket_close) {
245- local_socket_close_locked(s->peer);
246- } else {
247- s->peer->close(s->peer);
234+ if (s->peer->shutdown) {
235+ s->peer->shutdown(s->peer);
248236 }
249- s->peer = 0;
237+ s->peer->peer = nullptr;
238+ s->peer->close(s->peer);
239+ s->peer = nullptr;
250240 }
251241
252242 /* If we are already closing, or if there are no
--- /dev/null
+++ b/adb/sysdeps/mutex.h
@@ -0,0 +1,143 @@
1+#pragma once
2+
3+/*
4+ * Copyright (C) 2016 The Android Open Source Project
5+ *
6+ * Licensed under the Apache License, Version 2.0 (the "License");
7+ * you may not use this file except in compliance with the License.
8+ * You may obtain a copy of the License at
9+ *
10+ * http://www.apache.org/licenses/LICENSE-2.0
11+ *
12+ * Unless required by applicable law or agreed to in writing, software
13+ * distributed under the License is distributed on an "AS IS" BASIS,
14+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+ * See the License for the specific language governing permissions and
16+ * limitations under the License.
17+ */
18+
19+#if defined(_WIN32)
20+
21+#include <windows.h>
22+
23+#include <android-base/macros.h>
24+
25+#include "adb.h"
26+
27+// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex.
28+// Therefore, implement our own using the Windows primitives.
29+// Put them directly into the std namespace, so that when they're actually available, the build
30+// breaks until they're removed.
31+
32+#include <mutex>
33+namespace std {
34+
35+// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class.
36+class recursive_mutex {
37+ public:
38+ recursive_mutex() {
39+ InitializeCriticalSection(&mutex_);
40+ }
41+
42+ ~recursive_mutex() {
43+ DeleteCriticalSection(&mutex_);
44+ }
45+
46+ void lock() {
47+ EnterCriticalSection(&mutex_);
48+ }
49+
50+ bool try_lock() {
51+ return TryEnterCriticalSection(&mutex_);
52+ }
53+
54+ void unlock() {
55+ LeaveCriticalSection(&mutex_);
56+ }
57+
58+ private:
59+ CRITICAL_SECTION mutex_;
60+
61+ DISALLOW_COPY_AND_ASSIGN(recursive_mutex);
62+};
63+
64+class mutex {
65+ public:
66+ mutex() {
67+ }
68+
69+ ~mutex() {
70+ }
71+
72+ void lock() {
73+ mutex_.lock();
74+ if (++lock_count_ != 1) {
75+ fatal("non-recursive mutex locked reentrantly");
76+ }
77+ }
78+
79+ void unlock() {
80+ if (--lock_count_ != 0) {
81+ fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_);
82+ }
83+ mutex_.unlock();
84+ }
85+
86+ bool try_lock() {
87+ if (!mutex_.try_lock()) {
88+ return false;
89+ }
90+
91+ if (lock_count_ != 0) {
92+ mutex_.unlock();
93+ return false;
94+ }
95+
96+ ++lock_count_;
97+ return true;
98+ }
99+
100+ private:
101+ recursive_mutex mutex_;
102+ size_t lock_count_ = 0;
103+};
104+
105+}
106+
107+#elif defined(__BIONIC__)
108+
109+// On M, the recovery image uses parts of adb that depends on recursive_mutex, and uses libstdc++,
110+// which lacks it.
111+
112+#include <pthread.h>
113+#include <mutex>
114+
115+#include <base/macros.h>
116+
117+class recursive_mutex {
118+ public:
119+ recursive_mutex() {
120+ }
121+
122+ ~recursive_mutex() {
123+ }
124+
125+ void lock() {
126+ pthread_mutex_lock(&mutex_);
127+ }
128+
129+ bool try_lock() {
130+ return pthread_mutex_trylock(&mutex_);
131+ }
132+
133+ void unlock() {
134+ pthread_mutex_unlock(&mutex_);
135+ }
136+
137+ private:
138+ pthread_mutex_t mutex_ = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
139+
140+ DISALLOW_COPY_AND_ASSIGN(recursive_mutex);
141+};
142+
143+#endif