]> granicus.if.org Git - strace/commitdiff
Add helper functions to clear/restore syserror
authorDmitry V. Levin <ldv@altlinux.org>
Fri, 18 Sep 2015 01:54:59 +0000 (01:54 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 19 Sep 2015 01:04:49 +0000 (04:04 +0300)
* defs.h (temporarily_clear_syserror, restore_cleared_syserror):
New prototypes.
* syscall.c (saved_u_error): New variable.
(temporarily_clear_syserror, restore_cleared_syserror): New functions.
* aio.c (sys_io_getevents): Use temporarily_clear_syserror
and restore_cleared_syserror.
* mq.c (sys_mq_timedreceive): Likewise.
* signal.c (sys_rt_sigtimedwait): Likewise.

aio.c
defs.h
mq.c
signal.c
syscall.c

diff --git a/aio.c b/aio.c
index e9d36e3ce515540c79dabc15a76239a8e16aad4b..1cbd533a051a38bf70193ecfea1b87ed3dea29cb 100644 (file)
--- a/aio.c
+++ b/aio.c
@@ -244,7 +244,14 @@ SYS_FUNC(io_getevents)
                        tprints("], ");
                }
 
+               /*
+                * Since the timeout parameter is read by the kernel
+                * on entering syscall, it has to be decoded the same way
+                * whether the syscall has failed or not.
+                */
+               temporarily_clear_syserror(tcp);
                print_timespec(tcp, tcp->u_arg[4]);
+               restore_cleared_syserror(tcp);
        }
        return 0;
 }
diff --git a/defs.h b/defs.h
index 1f0900b167b36a88b4f2596bfb056c57e63e08b1..119f9b44e24e7d1a9e7e76990afdd5f8413402f2 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -538,6 +538,9 @@ extern void get_regs(pid_t pid);
 extern int get_scno(struct tcb *tcp);
 extern const char *syscall_name(long scno);
 
+extern void temporarily_clear_syserror(struct tcb *);
+extern void restore_cleared_syserror(struct tcb *);
+
 extern int umoven(struct tcb *, long, unsigned int, void *);
 #define umove(pid, addr, objp) \
        umoven((pid), (addr), sizeof(*(objp)), (void *) (objp))
diff --git a/mq.c b/mq.c
index ca0cfdaf2831ddaa03b16eb60c893072c1838e7e..a0af211588c1332189999cb5b2b42c5e63b559b1 100644 (file)
--- a/mq.c
+++ b/mq.c
@@ -59,7 +59,14 @@ SYS_FUNC(mq_timedreceive)
        else {
                printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
                tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]);
+               /*
+                * Since the timeout parameter is read by the kernel
+                * on entering syscall, it has to be decoded the same way
+                * whether the syscall has failed or not.
+                */
+               temporarily_clear_syserror(tcp);
                printtv(tcp, tcp->u_arg[4]);
+               restore_cleared_syserror(tcp);
        }
        return 0;
 }
index 1df3fe5bed43b82e988a955e3e321e688b4898d2..ec1684ef82ecd6623982ad584c6076e470555519 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -673,7 +673,16 @@ SYS_FUNC(rt_sigtimedwait)
                /* syscall exit, and u_arg[1] was NULL */
                return 0;
        }
+
+       /*
+        * Since the timeout parameter is read by the kernel
+        * on entering syscall, it has to be decoded the same way
+        * whether the syscall has failed or not.
+        */
+       temporarily_clear_syserror(tcp);
        print_timespec(tcp, tcp->u_arg[2]);
+       restore_cleared_syserror(tcp);
+
        tprintf(", %lu", tcp->u_arg[3]);
        return 0;
 };
index b59388b364189df5442bc3ec47176234f46002cb..aaa44eada74e3a5745a52065254a1c217dcd6c6d 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -1131,6 +1131,21 @@ trace_syscall(struct tcb *tcp)
                trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
 }
 
+static int saved_u_error;
+
+void
+temporarily_clear_syserror(struct tcb *tcp)
+{
+       saved_u_error = tcp->u_error;
+       tcp->u_error = 0;
+}
+
+void
+restore_cleared_syserror(struct tcb *tcp)
+{
+       tcp->u_error = saved_u_error;
+}
+
 /*
  * Cannot rely on __kernel_[u]long_t being defined,
  * it is quite a recent feature of <asm/posix_types.h>.