Skip to content

bluetooth: fix GATT server DB exhaustion on disable/enable cycles#586

Merged
huangyulong3 merged 1 commit into
open-vela:devfrom
liuX10:fix/gatts-db-exhaustion
May 8, 2026
Merged

bluetooth: fix GATT server DB exhaustion on disable/enable cycles#586
huangyulong3 merged 1 commit into
open-vela:devfrom
liuX10:fix/gatts-db-exhaustion

Conversation

@liuX10
Copy link
Copy Markdown
Contributor

@liuX10 liuX10 commented May 7, 2026

Summary

Fix GATT server static DB exhaustion across disable/enable cycles.

bt_sal_gatt_server_disable() previously only unregistered GATT/ATT callbacks without cleaning up the server_db[] and server_svcs[] static arrays. Each disable/enable cycle left stale attributes occupying slots, so attr_count kept growing until it reached CONFIG_GATT_SERVER_MAX_ATTRIBUTES and new service registrations failed.

Changes:

  • bt_sal_gatt_server_disable() now iterates server_svcs[] and unregisters every active GATT service from the zephyr stack, deletes the associated SDP records, frees each attribute's user_data/uuid memory, and resets server_db/server_svcs/attr_count/svc_attr_count to their initial state before unregistering callbacks.
  • if_gatts_shutdown() is reordered to call bt_sal_gatt_server_disable() before freeing the upper-layer service list, ensuring zephyr-side unregistration completes while the static DB is still consistent.

Impact

  • Build: no Kconfig or API change
  • Hardware: applies to all targets using the zephyr GATT server backend
  • Compatibility: behavior change only on the disable path — resources are now fully released; no functional impact on normal enable/register/use flows
  • Memory: slightly more work in the disable path; prevents long-term slot leakage and eventual registration failures

Testing

  • Reviewed the user_data/uuid lifecycle in gatt_db_add() and remove_from_server_db() — the new free pattern matches existing cleanup semantics, no UAF/double-free introduced
  • Verified that bt_gatt_service_unregister() is synchronous in zephyr, so freeing attribute memory after unregistration is safe
  • Manual scenario verification (from the original bug log): repeated gatts register → disable → enable cycles no longer leave stale server_db entries

manager->services = NULL;
bt_list_free(manager->pend_ops);
manager->pend_ops = NULL;
manager->started = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mind:manager->started = false now executes after bt_sal_gatt_server_disable() rather than before

@liuX10 liuX10 force-pushed the fix/gatts-db-exhaustion branch from ed15c8f to 9633e03 Compare May 8, 2026 07:06
bug: v/87180

bt_sal_gatt_server_disable() only unregistered callbacks without
cleaning up server_db[] and server_svcs[] static arrays. Each
disable/enable cycle left stale attributes occupying slots, causing
attr_count to eventually reach CONFIG_GATT_SERVER_MAX_ATTRIBUTES.

- Add full resource cleanup in bt_sal_gatt_server_disable(): unregister
  all GATT services from zephyr, free SDP records, release all
  attribute user_data/uuid memory, and reset server_db/server_svcs/
  attr_count/svc_attr_count.
- Reorder if_gatts_shutdown() to call disable before freeing the
  upper-layer service list, ensuring zephyr unregister completes first.

Signed-off-by: liuxiang18 <liuxiang18@xiaomi.com>
@liuX10 liuX10 force-pushed the fix/gatts-db-exhaustion branch from 9633e03 to bed5b90 Compare May 8, 2026 08:08
@huangyulong3 huangyulong3 merged commit 528af1d into open-vela:dev May 8, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants