forked from enlightenment/efl
ecore: detect and emit event on system time changed.
If we have timerfd then we can set a timer with special features (ABSTIME | CANCELON) to be notified if its offset to monotonic time change, effectively this will alert us if user called settimeofday() or similar method to change system time. This code was inspired by Enlightenment's clock module.
This commit is contained in:
parent
0a9c78896b
commit
ca39ff976e
|
@ -127,6 +127,13 @@ epoll_ctl(int epfd EINA_UNUSED,
|
||||||
# endif
|
# endif
|
||||||
#endif /* HAVE_SYS_TIMERFD_H */
|
#endif /* HAVE_SYS_TIMERFD_H */
|
||||||
|
|
||||||
|
#ifndef TFD_TIMER_ABSTIME
|
||||||
|
# define TFD_TIMER_ABSTIME (1 << 0)
|
||||||
|
#endif
|
||||||
|
#ifndef TFD_TIMER_CANCELON_SET
|
||||||
|
# define TFD_TIMER_CANCELON_SET (1 << 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_TIMERFD_CREATE
|
#ifndef HAVE_TIMERFD_CREATE
|
||||||
static inline int
|
static inline int
|
||||||
timerfd_create(int clockid EINA_UNUSED,
|
timerfd_create(int clockid EINA_UNUSED,
|
||||||
|
@ -763,6 +770,67 @@ static GSourceFuncs ecore_gsource_funcs =
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TIMERFD_H
|
||||||
|
static int realtime_fd = -1;
|
||||||
|
|
||||||
|
static void detect_time_changes_start(void);
|
||||||
|
static Eina_Bool
|
||||||
|
_realtime_update(void *data EINA_UNUSED, Ecore_Fd_Handler *fdh EINA_UNUSED)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if (read(realtime_fd, buf, sizeof(buf)) >= 0) return EINA_TRUE;
|
||||||
|
|
||||||
|
DBG("system clock changed");
|
||||||
|
ecore_event_add(ECORE_EVENT_SYSTEM_TIMEDATE_CHANGED, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
close(realtime_fd);
|
||||||
|
realtime_fd = -1;
|
||||||
|
detect_time_changes_start();
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
detect_time_changes_start(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYS_TIMERFD_H
|
||||||
|
struct itimerspec its;
|
||||||
|
|
||||||
|
if (realtime_fd >= 0) return;
|
||||||
|
|
||||||
|
realtime_fd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||||
|
if (realtime_fd < 0) return;
|
||||||
|
|
||||||
|
memset(&its, 0, sizeof(its));
|
||||||
|
if (timerfd_settime(realtime_fd,
|
||||||
|
TFD_TIMER_ABSTIME | TFD_TIMER_CANCELON_SET,
|
||||||
|
&its, NULL) < 0)
|
||||||
|
{
|
||||||
|
WRN("Couldn't arm timerfd to detect clock changes: %s",
|
||||||
|
strerror(errno));
|
||||||
|
close(realtime_fd);
|
||||||
|
realtime_fd = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecore_main_fd_handler_add(realtime_fd, ECORE_FD_READ,
|
||||||
|
_realtime_update, NULL, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
detect_time_changes_stop(void)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_SYS_TIMERFD_H
|
||||||
|
if (realtime_fd > 0)
|
||||||
|
{
|
||||||
|
close(realtime_fd);
|
||||||
|
realtime_fd = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_ecore_main_loop_init(void)
|
_ecore_main_loop_init(void)
|
||||||
{
|
{
|
||||||
|
@ -818,6 +886,8 @@ _ecore_main_loop_init(void)
|
||||||
CRIT("Failed to attach glib source to default context");
|
CRIT("Failed to attach glib source to default context");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
detect_time_changes_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -831,6 +901,8 @@ _ecore_main_loop_shutdown(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
detect_time_changes_stop();
|
||||||
|
|
||||||
if (epoll_fd >= 0)
|
if (epoll_fd >= 0)
|
||||||
{
|
{
|
||||||
close(epoll_fd);
|
close(epoll_fd);
|
||||||
|
|
Loading…
Reference in New Issue