Fix: Avoid overwriting the first error set by sem_wait()
Some functions (sem_trywait()) inside wd_delete() may fail and set the
errorno. this would override the any errors set by previous logic.
In recursice  error scenario, catch the first error and set it as errorno
@@ -124,6 +124,7 @@ int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay)
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
irqstate_t flags;
systime_t elapsed;
+ int errcode = OK;
int ret = ERROR;
DEBUGASSERT(sem != NULL && up_interrupt_context() == false && rtcb->waitdog == NULL);
@@ -163,7 +164,7 @@ int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay)
if (delay == 0) {
/* Return the errno from sem_trywait() */
-
+ errcode = get_errno();
goto errout_with_irqdisabled;
}
@@ -171,7 +172,8 @@ int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay)
elapsed = clock_systimer() - start;
if (/* elapsed >= (UINT32_MAX / 2) || */ elapsed >= delay) {
- set_errno(ETIMEDOUT);
+ /* Already timedout as elapsed time is more than required delay */
+ errcode = ETIMEDOUT;
goto errout_with_irqdisabled;
}
@@ -184,6 +186,10 @@ int sem_tickwait(FAR sem_t *sem, systime_t start, uint32_t delay)
/* Now perform the blocking wait */
ret = sem_wait(sem);
+ if (ret != OK) {
+ /* Return the errorcode set either by sem_wait() or sem_timeout() */
+ errcode = get_errno();
+ }
/* Stop the watchdog timer */
@@ -201,5 +207,12 @@ errout_with_irqdisabled:
irqrestore(flags);
wd_delete(rtcb->waitdog);
rtcb->waitdog = NULL;
+ /* some functions (sem_trywait()) inside wd_delete() may fail and set the
+ * errorno. this would override the any errors set above. In recursice
+ * error scenario, catch the first error and set it as errorno.
+ */
+ if (errcode != OK) {
+ set_errno(errcode);
+ }
return ret;
}
