Module: xenomai-2.5
Branch: master
Commit: 21c91b544dfb7d6bb8f4157708fc734d47f0bccb
URL:    
http://git.xenomai.org/?p=xenomai-2.5.git;a=commit;h=21c91b544dfb7d6bb8f4157708fc734d47f0bccb

Author: Gilles Chanteperdrix <gilles.chanteperd...@xenomai.org>
Date:   Mon Mar  8 16:24:09 2010 +0100

posix: fix pthread_cond_*wait return value overwriting

This fix uses errno to remember, at the time of the epilogue, the value
returned by the prologue. It will not work if cond_*wait are interrupted
by signals, and the signal handler uses a system call which overrides errno.

---

 ksrc/skins/posix/syscall.c |   25 +++++++++++++++++--------
 1 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/ksrc/skins/posix/syscall.c b/ksrc/skins/posix/syscall.c
index 6c3ec3a..2a97a2d 100644
--- a/ksrc/skins/posix/syscall.c
+++ b/ksrc/skins/posix/syscall.c
@@ -1520,7 +1520,7 @@ static int __pthread_cond_wait_prologue(struct pt_regs 
*regs)
        union __xeno_mutex mx, *umx;
        unsigned timed, count;
        struct timespec ts;
-       int err;
+       int err, perr = 0;
 
        ucnd = (union __xeno_cond *)__xn_reg_arg1(regs);
        umx = (union __xeno_mutex *)__xn_reg_arg2(regs);
@@ -1560,7 +1560,10 @@ static int __pthread_cond_wait_prologue(struct pt_regs 
*regs)
                                                    &mx.shadow_mutex,
                                                    &count, timed, XN_INFINITE);
 
-       if (err == 0 || err == ETIMEDOUT) {
+       switch(err) {
+       case 0:
+       case ETIMEDOUT:
+               perr = errno = err;
                err = -pse51_cond_timedwait_epilogue(cur, &cnd.shadow_cond,
                                                    &mx.shadow_mutex, count);
                if (err == 0 &&
@@ -1569,14 +1572,20 @@ static int __pthread_cond_wait_prologue(struct pt_regs 
*regs)
                                           &mx.shadow_mutex.lockcnt,
                                           sizeof(umx->shadow_mutex.lockcnt)))
                        return -EFAULT;
+               break;
+
+       case EINTR:
+               perr = err;
+               errno = 0;      /* epilogue should return 0. */
+               break;
        }
 
-       if (err == EINTR
-           && __xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
-                                     &count, sizeof(count)))
+       if (err == EINTR 
+           &&__xn_safe_copy_to_user((void __user *)__xn_reg_arg3(regs),
+                                    &count, sizeof(count)))
                        return -EFAULT;
-       
-       return -err;
+
+       return err == 0 ? -perr : -err;
 }
 
 /* pthread_cond_wait_epilogue(cond, mutex, count) */
@@ -1618,7 +1627,7 @@ static int __pthread_cond_wait_epilogue(struct pt_regs 
*regs)
                                      sizeof(umx->shadow_mutex.lockcnt)))
                return -EFAULT;
 
-       return err;
+       return err == 0 ? -errno : err;
 }
 
 static int __pthread_cond_signal(struct pt_regs *regs)


_______________________________________________
Xenomai-git mailing list
Xenomai-git@gna.org
https://mail.gna.org/listinfo/xenomai-git

Reply via email to