diff options
author | Phus Lu <phus.lu@citrix.com> | 2016-07-14 12:17:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-14 12:17:11 +0100 |
commit | a5596c503d9cfd2eb2d7a3304ebeb6591596c239 (patch) | |
tree | 26821894eff1ca24cc4160ef884feff2af3320aa | |
parent | 9cf1fde2f55d57f4ca5ab06d6aef64ca768640e5 (diff) | |
parent | b0091d3dad6a1dae7874ed33906ac0d64eb6c25b (diff) | |
download | vyos-xe-guest-utilities-a5596c503d9cfd2eb2d7a3304ebeb6591596c239.tar.gz vyos-xe-guest-utilities-a5596c503d9cfd2eb2d7a3304ebeb6591596c239.zip |
Merge pull request #16 from rosslagerwall/ca202608
CA-202608: Trigger refresh after system resume
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | mk/Makefile.deb | 1 | ||||
-rw-r--r-- | mk/Makefile.rpm | 1 | ||||
-rw-r--r-- | mk/Makefile.tgz | 1 | ||||
-rw-r--r-- | system/system.go | 76 | ||||
-rw-r--r-- | xe-daemon/xe-daemon.go | 8 |
6 files changed, 88 insertions, 0 deletions
@@ -30,6 +30,7 @@ endif XE_DAEMON_SOURCES := XE_DAEMON_SOURCES += ./xe-daemon/xe-daemon.go XE_DAEMON_SOURCES += ./syslog/syslog.go +XE_DAEMON_SOURCES += ./system/system.go XE_DAEMON_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.deb b/mk/Makefile.deb index e22a207..496f332 100644 --- a/mk/Makefile.deb +++ b/mk/Makefile.deb @@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.rpm b/mk/Makefile.rpm index d7bd7d5..de1fde2 100644 --- a/mk/Makefile.rpm +++ b/mk/Makefile.rpm @@ -35,6 +35,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go diff --git a/mk/Makefile.tgz b/mk/Makefile.tgz index 86c6995..7b19f26 100644 --- a/mk/Makefile.tgz +++ b/mk/Makefile.tgz @@ -38,6 +38,7 @@ GO_SOURCE_REPO = $(call git_loc,xe-guest-utilities) XE_DAEMON_GO_SOURCES := XE_DAEMON_GO_SOURCES += ./xe-daemon/xe-daemon.go # this should be the first one XE_DAEMON_GO_SOURCES += ./syslog/syslog.go +XE_DAEMON_GO_SOURCES += ./system/system.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric.go XE_DAEMON_GO_SOURCES += ./guestmetric/guestmetric_linux.go XE_DAEMON_GO_SOURCES += ./xenstoreclient/xenstore.go diff --git a/system/system.go b/system/system.go new file mode 100644 index 0000000..b21d000 --- /dev/null +++ b/system/system.go @@ -0,0 +1,76 @@ +package sys + +import ( + "math" + "syscall" + "time" + "unsafe" +) + +const ( + CLOCK_REALTIME = 0 + TFD_CLOEXEC = 02000000 + TFD_TIMER_ABSTIME = 1 + TFD_TIMER_CANCEL_ON_SET = 2 +) + +type ITimerSpec struct { + Interval syscall.Timespec + Value syscall.Timespec +} + +// System call wrapper for timerfd_create, generated with mksyscall.pl +func timerfdCreate(clockid int, flags int) (fd int, err error) { + r0, _, e1 := syscall.Syscall(syscall.SYS_TIMERFD_CREATE, + uintptr(clockid), uintptr(flags), 0) + fd = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// System call wrapper for timerfd_settime, generated with mksyscall.pl +func timerfdSettime(fd int, flags int, new_value *ITimerSpec, + old_value *ITimerSpec) (err error) { + _, _, e1 := syscall.Syscall6(syscall.SYS_TIMERFD_SETTIME, uintptr(fd), + uintptr(flags), + uintptr(unsafe.Pointer(new_value)), + uintptr(unsafe.Pointer(old_value)), 0, 0) + if e1 != 0 { + err = e1 + } + return +} + +/* + * Send a notification on @c when the system has just been resumed after + * sleep. This is implemented by watching for a change in real time compared + * with monotonic time. This may cause a spurious notification if the time + * is changed by a user or NTP jump. + */ +func NotifyResumed(c chan int) { + ts := ITimerSpec{Interval: syscall.Timespec{math.MaxInt32, 0}, + Value: syscall.Timespec{0, 0}} + buf := make([]byte, 8) + for { + fd, err := timerfdCreate(CLOCK_REALTIME, TFD_CLOEXEC) + if err != nil { + return + } + + err = timerfdSettime(fd, TFD_TIMER_ABSTIME|TFD_TIMER_CANCEL_ON_SET, &ts, nil) + if err != nil { + return + } + + _, err = syscall.Read(fd, buf) + if err == syscall.ECANCELED { + // Wait a bit for the system to settle down after resuming + time.Sleep(time.Duration(1) * time.Second) + c <- 1 + } + + syscall.Close(fd) + } +} diff --git a/xe-daemon/xe-daemon.go b/xe-daemon/xe-daemon.go index 839e454..17c4bfd 100644 --- a/xe-daemon/xe-daemon.go +++ b/xe-daemon/xe-daemon.go @@ -3,6 +3,7 @@ package main import ( guestmetric "../guestmetric" syslog "../syslog" + system "../system" xenstoreclient "../xenstoreclient" "flag" "fmt" @@ -52,6 +53,9 @@ func main() { exitChannel := make(chan os.Signal, 1) signal.Notify(exitChannel, syscall.SIGTERM, syscall.SIGINT) + resumedChannel := make(chan int) + go system.NotifyResumed(resumedChannel) + xs, err := xenstoreclient.NewCachedXenstore(0) if err != nil { message := fmt.Sprintf("NewCachedXenstore error: %v\n", err) @@ -135,6 +139,10 @@ func main() { } return + case <-resumedChannel: + logger.Printf("Trigger refresh after system resume\n") + continue + case <-time.After(time.Duration(*sleepInterval) * time.Second): continue } |