From 2181f1a4a428926da214b94327c3bcef9d283522 Mon Sep 17 00:00:00 2001 From: Nitin Shivpure Date: Sun, 6 Sep 2015 15:04:01 +0530 Subject: [PATCH] Fix PAN crash due to fd mismatch A case, where tap read thread is always exist, Sometimes data packets get recieved on older fd, which is not available. which is causing assert due to fd mismatch in race condition. when next pan connection is immediately available. If last pan connection gets disconnected, then tap_read_thread should be destroyed in btif context to fix this issue. Bug: 24093456 Change-Id: Ic1053200a7be4c2091d6c394634831ca3fbd61df --- bta/pan/bta_pan_act.c | 4 ---- btif/src/btif_pan.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c index 0b2a88898..84b82b3b9 100644 --- a/bta/pan/bta_pan_act.c +++ b/bta/pan/bta_pan_act.c @@ -601,7 +601,6 @@ void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) if(p_data->conn.result == PAN_SUCCESS) { data.status = BTA_PAN_SUCCESS; - bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr); p_scb->pan_flow_enable = TRUE; p_scb->app_flow_enable = TRUE; bta_sys_conn_open(BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); @@ -648,7 +647,6 @@ void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) data.handle = p_data->hdr.layer_specific; - bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); /* free all queued up data buffers */ @@ -657,8 +655,6 @@ void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) GKI_init_q(&p_scb->data_queue); - bta_pan_co_close(p_scb->handle, p_scb->app_id); - bta_pan_scb_dealloc(p_scb); bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data); diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c index fc05e2369..f7c0e0ca3 100644 --- a/btif/src/btif_pan.c +++ b/btif/src/btif_pan.c @@ -276,10 +276,10 @@ static bt_status_t btpan_disconnect(const bt_bdaddr_t *bd_addr) btpan_conn_t* conn = btpan_find_conn_addr(bd_addr->address); if (conn && conn->handle >= 0) { - BTA_PanClose(conn->handle); /* Inform the application that the disconnect has been initiated successfully */ btif_transfer_context(btif_in_pan_generic_evt, BTIF_PAN_CB_DISCONNECTING, (char *)bd_addr, sizeof(bt_bdaddr_t), NULL); + BTA_PanClose(conn->handle); return BT_STATUS_SUCCESS; } return BT_STATUS_FAIL; @@ -491,6 +491,62 @@ btpan_conn_t* btpan_find_conn_addr(const BD_ADDR addr) return NULL; } +static void btpan_open_conn(btpan_conn_t* conn, tBTA_PAN *p_data) +{ + BTIF_TRACE_API("btpan_open_conn: local_role:%d, peer_role: %d, handle:%d, conn: %p", + p_data->open.local_role, p_data->open.peer_role, p_data->open.handle, conn); + + if (conn == NULL) + conn = btpan_new_conn(p_data->open.handle, p_data->open.bd_addr, p_data->open.local_role, + p_data->open.peer_role); + if (conn) + { + BTIF_TRACE_DEBUG("btpan_open_conn:tap_fd:%d, open_count:%d, " + "conn->handle:%d should = handle:%d, local_role:%d, remote_role:%d", + btpan_cb.tap_fd, btpan_cb.open_count, conn->handle, p_data->open.handle, + conn->local_role, conn->remote_role); + + btpan_cb.open_count++; + conn->handle = p_data->open.handle; + if (btpan_cb.tap_fd < 0) + { + btpan_cb.tap_fd = btpan_tap_open(); + if(btpan_cb.tap_fd >= 0) + create_tap_read_thread(btpan_cb.tap_fd); + } + + if (btpan_cb.tap_fd >= 0) + { + btpan_cb.flow = 1; + conn->state = PAN_STATE_OPEN; + } + } +} + +static void btpan_close_conn(btpan_conn_t* conn) +{ + BTIF_TRACE_API("btpan_close_conn: %p",conn); + + if (conn && conn->state == PAN_STATE_OPEN) + { + BTIF_TRACE_DEBUG("btpan_close_conn: PAN_STATE_OPEN"); + + conn->state = PAN_STATE_CLOSE; + btpan_cb.open_count--; + + if (btpan_cb.open_count == 0) + { + destroy_tap_read_thread(); + if (btpan_cb.tap_fd != INVALID_FD) + { + btpan_tap_close(btpan_cb.tap_fd); + btpan_cb.tap_fd = INVALID_FD; + } + } + } +} + + static void btpan_cleanup_conn(btpan_conn_t* conn) { if (conn) @@ -615,6 +671,7 @@ static void bta_pan_callback_transfer(UINT16 event, char *p_param) { state = BTPAN_STATE_CONNECTED; status = BT_STATUS_SUCCESS; + btpan_open_conn(conn, p_data); } else { @@ -635,6 +692,7 @@ static void bta_pan_callback_transfer(UINT16 event, char *p_param) btpan_conn_t* conn = btpan_find_conn_handle(p_data->close.handle); LOG_INFO(LOG_TAG, "%s: event = BTA_PAN_CLOSE_EVT handle %d", __FUNCTION__, p_data->close.handle); + btpan_close_conn(conn); if (conn && conn->handle >= 0) { -- 2.11.0