esp_netif: list lock/unlock
Posted: Tue Apr 06, 2021 9:39 am
ESP-IDF V4.2
Two threads call esp_netif_new(), that calls esp_netif_get_handle_from_ifkey(), that calls esp_netif_list_lock()
The first thread creates and takes the semaphore; the second waits for xSemaphoreTake() returning.
The first threads gives the semaphore then delete it, beeing s_esp_netif_counter still zero.
When the second thread calls esp_netif_unlock() assert(s_list_lock) fails beeing the semaphore handle NULL.
The semaphore cannot protect itself.
Code from esp_netif_objects.c
Two threads call esp_netif_new(), that calls esp_netif_get_handle_from_ifkey(), that calls esp_netif_list_lock()
The first thread creates and takes the semaphore; the second waits for xSemaphoreTake() returning.
The first threads gives the semaphore then delete it, beeing s_esp_netif_counter still zero.
When the second thread calls esp_netif_unlock() assert(s_list_lock) fails beeing the semaphore handle NULL.
The semaphore cannot protect itself.
Code from esp_netif_objects.c
- static size_t s_esp_netif_counter = 0;
- esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
- {
- // mandatory configuration must be provided when creating esp_netif object
- if (esp_netif_config == NULL ||
- esp_netif_config->base->if_key == NULL ||
- NULL != esp_netif_get_handle_from_ifkey(esp_netif_config->base->if_key)) {
- ESP_LOGE(TAG, "%s: Failed to configure netif with config=%p (config or if_key is NULL or duplicate key)",
- __func__, esp_netif_config);
- return NULL;
- }
- …
- }
- esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
- {
- esp_err_t ret;
- if ((ret = esp_netif_list_lock()) != ESP_OK) {
- ESP_LOGE(TAG, "Failed to lock esp-netif list with %d", ret);
- return NULL;
- }
- esp_netif_t *esp_netif = esp_netif_next_unsafe(NULL);
- do {
- if (esp_netif && strcmp(if_key, esp_netif_get_ifkey(esp_netif))==0) {
- esp_netif_list_unlock();
- return esp_netif;
- }
- } while (NULL != (esp_netif = esp_netif_next_unsafe(esp_netif)));
- esp_netif_list_unlock();
- return NULL;
- }
- void esp_netif_list_unlock(void)
- {
- assert(s_list_lock);
- xSemaphoreGive(s_list_lock);
- if(s_esp_netif_counter == 0) {
- vQueueDelete(s_list_lock);
- s_list_lock = NULL;
- }
- }
- esp_err_t esp_netif_list_lock(void)
- {
- if (s_list_lock == NULL) {
- s_list_lock = xSemaphoreCreateMutex();
- if (s_list_lock == NULL) {
- return ESP_ERR_NO_MEM;
- }
- }
- xSemaphoreTake(s_list_lock, portMAX_DELAY);
- return ESP_OK;
- }