• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

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

system/core


Commit MetaInfo

Révision3e872c4ce7d83fee2673694644559f6fa9bdcbe0 (tree)
l'heure2016-07-20 18:01:29
AuteurDu, Changbin <changbin.du@inte...>
CommiterChih-Wei Huang

Message de Log

adb: sockets: fix race condition between input_thread and fdevent callback

The transport's input_thread clean up all of its sockets by
close_all_sockets function before it exit. All sockets's callback is
invoked by local_socket_event_func by fdevent thread(the main thread).

But there is no synchronization between these two thread. Missing
synchronization can cause crash or unexpected behaviour. So far has
observed two crash issue:
1. after close_all_sockets return, still has sockets pending. Then when

the pending sockets try to access the removed transport cause segment
fault.

2. calling the socket's close callback(local_socket_close) but a socket

has been destroied. This will access a freed memory.

Change-Id: I9787b9ca7949946e977e102812518799051b9c67
Tracked-On: https://jira01.devtools.intel.com/browse/OAM-12574
Signed-off-by: Du, Changbin <changbin.du@intel.com>
Reviewed-on: https://android.intel.com:443/461670

Change Summary

Modification

--- a/adb/adb.h
+++ b/adb/adb.h
@@ -85,6 +85,13 @@ struct asocket {
8585 ** but packets are still queued for delivery
8686 */
8787 int closing;
88+ /* flag: set when this socket is running.
89+ */
90+ int running;
91+ /* flag: force close this socket. if this socket is running, other
92+ ** thread set this flag to request close it.
93+ */
94+ int force_close;
8895
8996 /* flag: quit adbd when both ends close the
9097 ** local service socket
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -53,16 +53,13 @@ static asocket local_socket_closing_list = {
5353 .prev = &local_socket_closing_list,
5454 };
5555
56-// Parse the global list of sockets to find one with id |local_id|.
57-// If |peer_id| is not 0, also check that it is connected to a peer
58-// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
59-asocket *find_local_socket(unsigned local_id, unsigned peer_id)
56+static asocket *
57+find_socket_in_list(asocket *list, unsigned local_id, unsigned peer_id)
6058 {
6159 asocket *s;
6260 asocket *result = NULL;
6361
64- adb_mutex_lock(&socket_list_lock);
65- for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
62+ for (s = list->next; s != list; s = s->next) {
6663 if (s->id != local_id)
6764 continue;
6865 if (peer_id == 0 || (s->peer && s->peer->id == peer_id)) {
@@ -70,11 +67,24 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id)
7067 }
7168 break;
7269 }
73- adb_mutex_unlock(&socket_list_lock);
7470
7571 return result;
7672 }
7773
74+
75+// Parse the global list of sockets to find one with id |local_id|.
76+// If |peer_id| is not 0, also check that it is connected to a peer
77+// with id |peer_id|. Returns an asocket handle on success, NULL on failure.
78+asocket *find_local_socket(unsigned local_id, unsigned peer_id)
79+{
80+ asocket *result = NULL;
81+
82+ adb_mutex_lock(&socket_list_lock);
83+ result = find_socket_in_list(&local_socket_list, local_id, peer_id);
84+ adb_mutex_unlock(&socket_list_lock);
85+ return result;
86+}
87+
7888 static void
7989 insert_local_socket(asocket* s, asocket* list)
8090 {
@@ -113,10 +123,14 @@ void remove_socket(asocket *s)
113123 }
114124 }
115125
126+// Note: after return, all sockets refer to transport @t should be closed.
127+// (Because the atransport is going to removed.)
128+// force_close && running flag are to implement this.
116129 void close_all_sockets(atransport *t)
117130 {
118131 asocket *s;
119132
133+ D("close all sockets of transport %p\n", t);
120134 /* this is a little gross, but since s->close() *will* modify
121135 ** the list out from under you, your options are limited.
122136 */
@@ -124,7 +138,17 @@ void close_all_sockets(atransport *t)
124138 restart:
125139 for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
126140 if(s->transport == t || (s->peer && s->peer->transport == t)) {
127- local_socket_close_locked(s);
141+ // set force_close flag since transport is going to be removed.
142+ // we need ensure the socket is closed after we return.
143+ s->force_close = 1;
144+ // avoid race condition with pending fdevent
145+ if (s->running) {
146+ // unlock to give a chance to close socket after running
147+ adb_mutex_unlock(&socket_list_lock);
148+ adb_sleep_ms(10); // sleep to relax cpu
149+ adb_mutex_lock(&socket_list_lock);
150+ } else
151+ local_socket_close_locked(s);
128152 goto restart;
129153 }
130154 }
@@ -193,8 +217,18 @@ static void local_socket_ready(asocket *s)
193217
194218 static void local_socket_close(asocket *s)
195219 {
220+ unsigned local_id = s->id;
221+ unsigned peer_id = s->peer ? s->peer->id : 0;
222+ asocket *sk;
223+
196224 adb_mutex_lock(&socket_list_lock);
197- local_socket_close_locked(s);
225+ // we may race with close_all_sockets (called by input-thread),
226+ // so need to check if socket already destoried.
227+ sk = find_socket_in_list(&local_socket_list, local_id, peer_id);
228+ if (!sk)
229+ sk = find_socket_in_list(&local_socket_closing_list, local_id, peer_id);
230+ if (sk)
231+ local_socket_close_locked(s);
198232 adb_mutex_unlock(&socket_list_lock);
199233 }
200234
@@ -250,9 +284,10 @@ static void local_socket_close_locked(asocket *s)
250284 }
251285
252286 /* If we are already closing, or if there are no
253- ** pending packets, destroy immediately
287+ ** pending packets, or need force close it, then
288+ ** destroy immediately.
254289 */
255- if (s->closing || s->pkt_first == NULL) {
290+ if (s->closing || s->force_close || s->pkt_first == NULL) {
256291 int id = s->id;
257292 local_socket_destroy(s);
258293 D("LS(%d): closed\n", id);
@@ -272,8 +307,12 @@ static void local_socket_close_locked(asocket *s)
272307 static void local_socket_event_func(int fd, unsigned ev, void* _s)
273308 {
274309 asocket* s = reinterpret_cast<asocket*>(_s);
310+ s->running = 1;
275311 D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
276312
313+ if (s->force_close)
314+ goto out;
315+
277316 /* put the FDE_WRITE processing before the FDE_READ
278317 ** in order to simplify the code.
279318 */
@@ -287,7 +326,7 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
287326 ** be processed in the next iteration loop
288327 */
289328 if (errno == EAGAIN) {
290- return;
329+ goto out;
291330 }
292331 } else if (r > 0) {
293332 p->ptr += r;
@@ -296,6 +335,7 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
296335 }
297336
298337 D(" closing after write because r=%d and errno is %d\n", r, errno);
338+ s->running = 0;
299339 s->close(s);
300340 return;
301341 }
@@ -314,6 +354,7 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
314354 */
315355 if (s->closing) {
316356 D(" closing because 'closing' is set after write\n");
357+ s->running = 0;
317358 s->close(s);
318359 return;
319360 }
@@ -372,7 +413,7 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
372413 ** this handler function will be called again
373414 ** to process FDE_WRITE events.
374415 */
375- return;
416+ goto out;
376417 }
377418
378419 if (r > 0) {
@@ -387,7 +428,9 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
387428 if ((s->fde.force_eof && !r) || is_eof) {
388429 D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n",
389430 is_eof, r, s->fde.force_eof);
431+ s->running = 0;
390432 s->close(s);
433+ return;
391434 }
392435 }
393436
@@ -398,7 +441,13 @@ static void local_socket_event_func(int fd, unsigned ev, void* _s)
398441 */
399442 D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
400443
401- return;
444+ goto out;
445+ }
446+out:
447+ s->running = 0;
448+ if (s->force_close) {
449+ D("LS(%d): force closing (fd=%d)\n", s->id, s->fd);
450+ s->close(s);
402451 }
403452 }
404453
@@ -406,6 +455,7 @@ asocket *create_local_socket(int fd)
406455 {
407456 asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
408457 if (s == NULL) fatal("cannot allocate socket");
458+ memset(s, 0, sizeof(asocket));
409459 s->fd = fd;
410460 s->enqueue = local_socket_enqueue;
411461 s->ready = local_socket_ready;
@@ -551,6 +601,7 @@ asocket *create_remote_socket(unsigned id, atransport *t)
551601 adisconnect* dis = &reinterpret_cast<aremotesocket*>(s)->disconnect;
552602
553603 if (s == NULL) fatal("cannot allocate socket");
604+ memset(s, 0, sizeof(asocket));
554605 s->id = id;
555606 s->enqueue = remote_socket_enqueue;
556607 s->ready = remote_socket_ready;
@@ -883,6 +934,7 @@ static asocket *create_smart_socket(void)
883934 D("Creating smart socket \n");
884935 asocket *s = reinterpret_cast<asocket*>(calloc(1, sizeof(asocket)));
885936 if (s == NULL) fatal("cannot allocate socket");
937+ memset(s, 0, sizeof(asocket));
886938 s->enqueue = smart_socket_enqueue;
887939 s->ready = smart_socket_ready;
888940 s->shutdown = NULL;