Skip to content

Commit b086e47

Browse files
committed
Return error if calling function will block host task
This will prevent applications from hanging forever when calling a blocking function from the host task.
1 parent 8370464 commit b086e47

8 files changed

Lines changed: 80 additions & 11 deletions

src/NimBLEClient.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,12 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
270270
goto error;
271271
}
272272

273+
if (!asyncConnect && NimBLEUtils::inHostTask()) {
274+
NIMBLE_LOGE(LOG_TAG, "Cannot connect synchronously from host task");
275+
rc = BLE_HS_EREJECT;
276+
goto error;
277+
}
278+
273279
m_connStatus = CONNECTING;
274280
m_peerAddress = address;
275281
m_config.asyncConnect = asyncConnect;
@@ -334,6 +340,11 @@ bool NimBLEClient::connect(const NimBLEAddress& address, bool deleteAttributes,
334340
*/
335341
bool NimBLEClient::secureConnection(bool async) const {
336342
NIMBLE_LOGD(LOG_TAG, ">> secureConnection()");
343+
if (!async && NimBLEUtils::inHostTask()) {
344+
NIMBLE_LOGE(LOG_TAG, "Cannot secure connection synchronously from host task");
345+
m_lastErr = BLE_HS_EREJECT;
346+
return false;
347+
}
337348

338349
int rc = 0;
339350
if (async && !NimBLEDevice::startSecurity(m_connHandle, &rc)) {
@@ -669,6 +680,10 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) {
669680
*/
670681
NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) {
671682
NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str());
683+
if (NimBLEUtils::inHostTask()) {
684+
NIMBLE_LOGE(LOG_TAG, "getService cannot be called from host task");
685+
return nullptr;
686+
}
672687

673688
for (auto& it : m_svcVec) {
674689
if (it->getUUID() == uuid) {

src/NimBLEDevice.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@ void NimBLEDevice::onSync(void) {
879879
*/
880880
void NimBLEDevice::host_task(void* param) {
881881
NIMBLE_LOGI(LOG_TAG, "NimBLE Started!");
882+
NimBLEUtils::m_hostTaskHandle = ble_npl_get_current_task_id();
882883
nimble_port_run(); // This function will return only when nimble_port_stop() is executed
883884
nimble_port_freertos_deinit();
884885
} // host_task

src/NimBLERemoteCharacteristic.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ bool NimBLERemoteCharacteristic::retrieveDescriptors(NimBLEDescriptorFilter* pFi
155155
*/
156156
NimBLERemoteDescriptor* NimBLERemoteCharacteristic::getDescriptor(const NimBLEUUID& uuid) const {
157157
NIMBLE_LOGD(LOG_TAG, ">> getDescriptor: uuid: %s", uuid.toString().c_str());
158+
if (NimBLEUtils::inHostTask()) {
159+
NIMBLE_LOGE(LOG_TAG, "getDescriptor cannot be called from host task");
160+
return nullptr;
161+
}
162+
158163
NimBLEUUID uuidTmp{uuid};
159164
NimBLETaskData taskData(const_cast<NimBLERemoteCharacteristic*>(this));
160165
NimBLEDescriptorFilter filter{nullptr, &uuidTmp, &taskData};

src/NimBLERemoteService.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const char* u
7575
*/
7676
NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEUUID& uuid) const {
7777
NIMBLE_LOGD(LOG_TAG, ">> getCharacteristic: uuid: %s", uuid.toString().c_str());
78+
if (NimBLEUtils::inHostTask()) {
79+
NIMBLE_LOGE(LOG_TAG, "getCharacteristic cannot be called from host task");
80+
return nullptr;
81+
}
82+
7883
NimBLERemoteCharacteristic* pChar = nullptr;
7984

8085
for (const auto& it : m_vChars) {
@@ -116,6 +121,11 @@ NimBLERemoteCharacteristic* NimBLERemoteService::getCharacteristic(const NimBLEU
116121
* @return A read-only reference to the vector of characteristics retrieved for this service.
117122
*/
118123
const std::vector<NimBLERemoteCharacteristic*>& NimBLERemoteService::getCharacteristics(bool refresh) const {
124+
if (refresh && NimBLEUtils::inHostTask()) {
125+
NIMBLE_LOGE(LOG_TAG, "cannot refresh characteristics from host task");
126+
return m_vChars;
127+
}
128+
119129
if (refresh) {
120130
deleteCharacteristics();
121131
retrieveCharacteristics();

src/NimBLERemoteValueAttribute.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ bool NimBLERemoteValueAttribute::writeValue(const uint8_t* data, size_t length,
4242
goto Done;
4343
}
4444

45+
if (NimBLEUtils::inHostTask()) {
46+
NIMBLE_LOGE(LOG_TAG, "writeValue cannot be called from the host task");
47+
return false;
48+
}
49+
4550
do {
4651
if (length > mtu) {
4752
NIMBLE_LOGI(LOG_TAG, "writeValue: long write");
@@ -123,6 +128,10 @@ int NimBLERemoteValueAttribute::onWriteCB(uint16_t conn_handle, const ble_gatt_e
123128
*/
124129
NimBLEAttValue NimBLERemoteValueAttribute::readValue(time_t* timestamp) {
125130
NIMBLE_LOGD(LOG_TAG, ">> readValue()");
131+
if (NimBLEUtils::inHostTask()) {
132+
NIMBLE_LOGE(LOG_TAG, "readValue cannot be called from the host task");
133+
return NimBLEAttValue();
134+
}
126135

127136
NimBLEAttValue value{};
128137
const NimBLEClient* pClient = getClient();

src/NimBLEScan.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,11 @@ NimBLEScanResults NimBLEScan::getResults(uint32_t duration, bool is_continue) {
678678
return m_scanResults;
679679
}
680680

681+
if (NimBLEUtils::inHostTask()) {
682+
NIMBLE_LOGE(LOG_TAG, "Cannot call blocking getResults from NimBLE host task");
683+
return m_scanResults;
684+
}
685+
681686
NimBLETaskData taskData;
682687
m_pTaskData = &taskData;
683688

src/NimBLEUtils.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
constexpr uint32_t TASK_BLOCK_BIT = (1 << MYNEWT_VAL(NIMBLE_CPP_FREERTOS_TASK_BLOCK_BIT));
7373
static const char* LOG_TAG = "NimBLEUtils";
7474

75+
void* NimBLEUtils::m_hostTaskHandle = nullptr;
76+
7577
/**
7678
* @brief Construct a NimBLETaskData instance.
7779
* @param [in] pInstance An instance of the class that will be waiting.
@@ -604,4 +606,21 @@ NimBLEAddress NimBLEUtils::generateAddr(bool nrpa) {
604606
return NimBLEAddress{addr};
605607
} // generateAddr
606608

609+
610+
/**
611+
* @brief Get the handle of the task that is running the NimBLE host.
612+
* @return The task handle or nullptr if there was an error.
613+
*/
614+
void* NimBLEUtils::getHostTaskHandle() {
615+
return m_hostTaskHandle;
616+
} // getHostTaskHandle
617+
618+
/**
619+
* @brief Check if the current task is the NimBLE host task.
620+
* @return True if the current task is the host task, false otherwise.
621+
*/
622+
bool NimBLEUtils::inHostTask() {
623+
return ble_npl_get_current_task_id() == NimBLEUtils::getHostTaskHandle();
624+
}
625+
607626
#endif // CONFIG_BT_NIMBLE_ENABLED

src/NimBLEUtils.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,16 @@
2929
# endif
3030
# endif
3131

32-
#if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) && !defined NDEBUG
33-
void nimble_cpp_assert(const char *file, unsigned line) __attribute((weak, noreturn));
34-
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? \
35-
__builtin_strrchr (__FILE__, '/') + 1 : __FILE__)
36-
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
37-
if (!(cond)) { \
38-
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
39-
}
40-
#else
41-
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
42-
#endif
32+
# if MYNEWT_VAL(NIMBLE_CPP_DEBUG_ASSERT_ENABLED) && !defined NDEBUG
33+
void nimble_cpp_assert(const char* file, unsigned line) __attribute((weak, noreturn));
34+
# define NIMBLE_ATT_VAL_FILE (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
35+
# define NIMBLE_CPP_DEBUG_ASSERT(cond) \
36+
if (!(cond)) { \
37+
nimble_cpp_assert(NIMBLE_ATT_VAL_FILE, __LINE__); \
38+
}
39+
# else
40+
# define NIMBLE_CPP_DEBUG_ASSERT(cond) (void(0))
41+
# endif
4342

4443
# include <string>
4544

@@ -74,6 +73,12 @@ class NimBLEUtils {
7473
static NimBLEAddress generateAddr(bool nrpa);
7574
static bool taskWait(const NimBLETaskData& taskData, uint32_t timeout);
7675
static void taskRelease(const NimBLETaskData& taskData, int rc = 0);
76+
static void* getHostTaskHandle();
77+
static bool inHostTask();
78+
79+
private:
80+
friend class NimBLEDevice;
81+
static void* m_hostTaskHandle;
7782
};
7883

7984
#endif // CONFIG_BT_NIMBLE_ENABLED

0 commit comments

Comments
 (0)