vSemaphoreDelete immediately after xSemaphoreTake

I am trying to track down an issue in the ESP-IDF; my version appears to be using FreeRTOS v10.2.1. In several places when cleaning up some obj, the code uses an idiom like this:

xSemaphoreTake(obj->semaphore_handle portMAX_DELAY);
vSemaphoreDelete(obj->semaphore_handle);

Is this safe? I have encountered a crash after this which I have “fixed” by removing the Take. In a couple of places I see this idiom:

xSemaphoreTake(obj->semaphore_handle, portMAX_DELAY);
xSemaphoreGive(obj->semaphore_handle);
vSemaphoreDelete(obj->semaphore_handle);

Is the second example “more correct”? I see several cautions not to delete a semaphore that is in use. Thanks.

Its hard to say if the code is correct or not without knowing what the semaphore is used for, but assuming the semaphore is not being used after it is deleted then I think it would only make a difference for mutex type semaphores. If the semaphore is a mutex then taking the semaphore could result in priority inheritance if a higher priority task attempted to take the same semaphore before it was deleted. Deleting the semaphore would mean the inherited priority would never be returned to back to its original priority. That would be a rare corner case though, and only be possible if something else was trying to take the semaphore at the same time - which would be dangerous even without priority inheritance if the semaphore is deleted immediately after.

Thank you for your reply. Sorry for not saying: it was created with xSemaphoreCreateMutex(). The specific code is esp-idf/i2c.c at 73db142403c6e5b763a0e1c07312200e9b622673 · espressif/esp-idf · GitHub. This may be a second-order bug of some kind.

Looking at the code I suspect it is taking the semaphore before deleting it to ensure the semaphore is not held by any other task before it gets deleted.