diff --git a/winsup/cygwin/fhandler_timerfd.cc b/winsup/cygwin/fhandler_timerfd.cc index 8a6c4b559..2a0521708 100644 --- a/winsup/cygwin/fhandler_timerfd.cc +++ b/winsup/cygwin/fhandler_timerfd.cc @@ -187,6 +187,35 @@ fhandler_timerfd::dup (fhandler_base *child, int flags) return ret; } +int +fhandler_timerfd::ioctl (unsigned int cmd, void *p) +{ + int ret = -1; + uint64_t exp_cnt; + + switch (cmd) + { + case TFD_IOC_SET_TICKS: + __try + { + timerfd_tracker *tfd = (timerfd_tracker *) timerid; + + exp_cnt = *(uint64_t *) p; + ret = tfd->ioctl_set_ticks (exp_cnt); + if (ret < 0) + set_errno (-ret); + } + __except (EFAULT) {} + __endtry + break; + default: + ret = fhandler_base::ioctl (cmd, p); + break; + } + syscall_printf ("%d = ioctl_timerfd(%x, %p)", ret, cmd, p); + return ret; +} + void fhandler_timerfd::fixup_after_fork (HANDLE) { @@ -214,39 +243,6 @@ fhandler_timerfd::fixup_after_exec () __endtry } -int -fhandler_timerfd::ioctl (unsigned int cmd, void *p) -{ - int ret = -1; - uint64_t exp_cnt; - - switch (cmd) - { - case TFD_IOC_SET_TICKS: - __try - { - timerfd_tracker *tfd = (timerfd_tracker *) timerid; - - exp_cnt = *(uint64_t *) p; - if (!exp_cnt) - { - set_errno (EINVAL); - break; - } - tfd->ioctl_set_ticks (exp_cnt); - ret = 0; - } - __except (EFAULT) {} - __endtry - break; - default: - ret = fhandler_base::ioctl (cmd, p); - break; - } - syscall_printf ("%d = ioctl_timerfd(%x, %p)", ret, cmd, p); - return ret; -} - fhandler_timerfd::~fhandler_timerfd () { __try diff --git a/winsup/cygwin/timerfd.cc b/winsup/cygwin/timerfd.cc index 08fff312c..a03749a60 100644 --- a/winsup/cygwin/timerfd.cc +++ b/winsup/cygwin/timerfd.cc @@ -394,11 +394,18 @@ timerfd_tracker::close () InterlockedDecrement (&tfd_shared->instance_count); } -void -timerfd_tracker::ioctl_set_ticks (uint64_t exp_cnt) +int +timerfd_tracker::ioctl_set_ticks (uint64_t new_exp_cnt) { + LONG64 exp_cnt = (LONG64) new_exp_cnt; + if (exp_cnt == 0 || exp_cnt == -1LL) + return -EINVAL; + if (!enter_critical_section ()) + return -EBADF; set_expiration_count (exp_cnt); timer_expired (); + leave_critical_section (); + return 0; } void diff --git a/winsup/cygwin/timerfd.h b/winsup/cygwin/timerfd.h index 1f9f76268..66bf78424 100644 --- a/winsup/cygwin/timerfd.h +++ b/winsup/cygwin/timerfd.h @@ -148,7 +148,7 @@ class timerfd_tracker /* cygheap! */ int settime (int, const struct itimerspec *, struct itimerspec *); static void dtor (timerfd_tracker *); void close (); - void ioctl_set_ticks (uint64_t); + int ioctl_set_ticks (uint64_t); void fixup_after_fork_exec (bool); void fixup_after_fork () { fixup_after_fork_exec (false); } void fixup_after_exec () { fixup_after_fork_exec (true); }