Fix places where the errno value was being overwritten by subsequent actions so that the returned errno value was incorrect. From Max Neklyudov.

This commit is contained in:
Gregory Nutt 2015-02-25 07:45:04 -06:00
parent 4521e082a9
commit 127951e029
2 changed files with 40 additions and 10 deletions

View File

@ -103,6 +103,7 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
FAR fd_set *exceptfds, FAR struct timeval *timeout)
{
struct pollfd *pollset;
int errcode;
int fd;
int npfds;
int msec;
@ -198,6 +199,12 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
/* Then let poll do all of the real work. */
ret = poll(pollset, npfds, msec);
if (ret < 0)
{
/* poll() failed! Save the errno value */
errcode = get_errno();
}
/* Now set up the return values */
@ -263,6 +270,16 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds,
}
kmm_free(pollset);
/* Did poll() fail above? */
if (ret < 0)
{
/* Yes.. restore the errno value */
set_errno(errcode);
}
return ret;
}

View File

@ -167,7 +167,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
FAR struct tcb_s *rtcb = (FAR struct tcb_s *)g_readytorun.head;
irqstate_t flags;
int ticks;
int err;
int errcode;
int ret = ERROR;
DEBUGASSERT(up_interrupt_context() == false && rtcb->waitdog == NULL);
@ -179,7 +179,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
#ifdef CONFIG_DEBUG
if (!abstime || !sem)
{
err = EINVAL;
errcode = EINVAL;
goto errout;
}
#endif
@ -192,7 +192,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
rtcb->waitdog = wd_create();
if (!rtcb->waitdog)
{
err = ENOMEM;
errcode = ENOMEM;
goto errout;
}
@ -225,7 +225,7 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
{
err = EINVAL;
errcode = EINVAL;
goto errout_disabled;
}
@ -233,31 +233,37 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
* disabled here so that this time stays valid until the wait begins.
*/
err = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
errcode = clock_abstime2ticks(CLOCK_REALTIME, abstime, &ticks);
/* If the time has already expired return immediately. */
if (err == OK && ticks <= 0)
if (errcode == OK && ticks <= 0)
{
err = ETIMEDOUT;
errcode = ETIMEDOUT;
goto errout_disabled;
}
/* Handle any time-related errors */
if (err != OK)
if (errcode != OK)
{
goto errout_disabled;
}
/* Start the watchdog */
err = OK;
errcode = OK;
wd_start(rtcb->waitdog, ticks, (wdentry_t)sem_timeout, 1, getpid());
/* Now perform the blocking wait */
ret = sem_wait(sem);
if (ret < 0)
{
/* sem_wait() failed. Save the errno value */
errcode = get_errno();
}
/* Stop the watchdog timer */
@ -275,6 +281,13 @@ int sem_timedwait(FAR sem_t *sem, FAR const struct timespec *abstime)
* cases.
*/
if (ret < 0)
{
/* On failure, restore the errno value returned by sem_wait */
set_errno(errcode);
}
return ret;
/* Error exits */
@ -285,6 +298,6 @@ errout_disabled:
rtcb->waitdog = NULL;
errout:
set_errno(err);
set_errno(errcode);
return ERROR;
}