summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-02-25 07:45:04 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-02-25 07:45:04 -0600
commitf9aaaea355c5686a6e627b886b7a56c4fa31ce1d (patch)
tree9e36cdeec8de7ac44f67190c62fc5f8d3a8a1845
parentd007ca9840471211479065f4b265f604ee5f6238 (diff)
downloadnuttx-f9aaaea355c5686a6e627b886b7a56c4fa31ce1d.tar.gz
nuttx-f9aaaea355c5686a6e627b886b7a56c4fa31ce1d.tar.bz2
nuttx-f9aaaea355c5686a6e627b886b7a56c4fa31ce1d.zip
Fix places where the errno value was being overwritten by subsequent actions so that the returned errno value was incorrect. From Max Neklyudov.
-rw-r--r--nuttx/fs/vfs/fs_select.c17
-rw-r--r--nuttx/sched/semaphore/sem_timedwait.c33
2 files changed, 40 insertions, 10 deletions
diff --git a/nuttx/fs/vfs/fs_select.c b/nuttx/fs/vfs/fs_select.c
index 6edf2b7c3..47fa65004 100644
--- a/nuttx/fs/vfs/fs_select.c
+++ b/nuttx/fs/vfs/fs_select.c
@@ -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;
}
diff --git a/nuttx/sched/semaphore/sem_timedwait.c b/nuttx/sched/semaphore/sem_timedwait.c
index b7d850728..4d5e58342 100644
--- a/nuttx/sched/semaphore/sem_timedwait.c
+++ b/nuttx/sched/semaphore/sem_timedwait.c
@@ -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;
}