Add is_erestart helper function

* defs.h (is_erestart): New prototype.
* syscall.c (is_erestart): New function.
* time.c (sys_nanosleep): Use is_erestart,
temporarily_clear_syserror, and restore_cleared_syserror.
This commit is contained in:
Дмитрий Левин 2015-09-18 01:54:59 +00:00
parent 3858b93ad9
commit 9af94a2f48
3 changed files with 25 additions and 13 deletions

1
defs.h
View File

@ -538,6 +538,7 @@ extern void get_regs(pid_t pid);
extern int get_scno(struct tcb *tcp);
extern const char *syscall_name(long scno);
extern bool is_erestart(struct tcb *);
extern void temporarily_clear_syserror(struct tcb *);
extern void restore_cleared_syserror(struct tcb *);

View File

@ -1131,6 +1131,20 @@ trace_syscall(struct tcb *tcp)
trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
}
bool
is_erestart(struct tcb *tcp)
{
switch (tcp->u_error) {
case ERESTARTSYS:
case ERESTARTNOINTR:
case ERESTARTNOHAND:
case ERESTART_RESTARTBLOCK:
return true;
default:
return false;
}
}
static int saved_u_error;
void

23
time.c
View File

@ -203,22 +203,19 @@ SYS_FUNC(nanosleep)
print_timespec(tcp, tcp->u_arg[0]);
tprints(", ");
} else {
/* Second (returned) timespec is only significant
* if syscall was interrupted. On success, we print
* only its address, since kernel doesn't modify it,
/*
* Second (returned) timespec is only significant if syscall
* was interrupted. On success and in case of other errors we
* print only its address, since kernel doesn't modify it,
* and printing the value may show uninitialized data.
*/
switch (tcp->u_error) {
default:
/* Not interrupted (slept entire interval) */
printaddr(tcp->u_arg[1]);
break;
case ERESTARTSYS:
case ERESTARTNOINTR:
case ERESTARTNOHAND:
case ERESTART_RESTARTBLOCK:
/* Interrupted */
if (is_erestart(tcp)) {
temporarily_clear_syserror(tcp);
print_timespec(tcp, tcp->u_arg[1]);
restore_cleared_syserror(tcp);
} else {
printaddr(tcp->u_arg[1]);
}
}
return 0;