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

Commit 356b4c46 authored by Nitin Shivpure's avatar Nitin Shivpure Committed by Andre Eisenbach
Browse files

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
parent 45bb20de
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -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);
+59 −1
Original line number Diff line number Diff line
@@ -273,10 +273,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;
@@ -488,6 +488,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)
@@ -612,6 +668,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
                {
@@ -632,6 +689,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("%s: event = BTA_PAN_CLOSE_EVT handle %d", __FUNCTION__, p_data->close.handle);
                btpan_close_conn(conn);

                if (conn && conn->handle >= 0)
                {