Skip to content

Commit

Permalink
improve golang instablility
Browse files Browse the repository at this point in the history
it looks like golang is unstable when using the win32 api

similar to golang/go#40722. Some error
messages:
 - Segmentation fault
 - Bad p
 - Missing stack in shrinkstack

Added logging to help debug. It looks like it is related to the
frequency of paint or InvalidateRect. Increasing the refresh speed
to 10ms can reliably reproduce the problem, at 500ms it seems pretty
stable
  • Loading branch information
KlotzAndrew committed Jan 30, 2022
1 parent 3f62069 commit 69477df
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 33 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1 +1,2 @@
*.exe
*.log
4 changes: 4 additions & 0 deletions go.mod
@@ -1,3 +1,7 @@
module actions-per-minute-tracker

go 1.17

require github.com/sirupsen/logrus v1.8.1

require golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect
10 changes: 10 additions & 0 deletions go.sum
@@ -0,0 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
58 changes: 25 additions & 33 deletions main.go
Expand Up @@ -2,13 +2,12 @@ package main

import (
"fmt"
"log"
"time"

"actions-per-minute-tracker/win32"
)

const refreshSignal = 35001
log "github.com/sirupsen/logrus"
)

type APMTracker struct {
hookKeyboard win32.HHOOK
Expand All @@ -24,7 +23,7 @@ func newAPMTracker() *APMTracker {
tracker := &APMTracker{
done: make(chan bool),
actionsPerSecond: []uint16{0},
newActions: make(chan int),
newActions: make(chan int, 10_000),
}
tracker.Start()

Expand Down Expand Up @@ -75,10 +74,11 @@ func adjustFirstMinute(rollingActions uint, currentWindowSize int) uint {
func (c *APMTracker) addAction() {
select {
case c.newActions <- 1:
case <-time.After(25 * time.Millisecond):
log.Debug("tracking: tool too long to process message")
default:
log.Fatalf("unable to track action")
log.Fatalf("unable to track action", len(c.newActions))
}

}

func (c *APMTracker) keyboardCallback(code int, wparam win32.WPARAM, lparam win32.LPARAM) win32.LRESULT {
Expand Down Expand Up @@ -106,8 +106,11 @@ func (c *APMTracker) mouseCallback(code int, wparam win32.WPARAM, lparam win32.L
return win32.CallNextHookEx(c.hookMouse, code, wparam, lparam)
}

// https://docs.microsoft.com/en-us/windows/win32/winmsg/using-window-procedures
func (r *APMTracker) windowProc(hwnd win32.HWND, msg uint32, wparam win32.WPARAM, lparam win32.LPARAM) win32.LRESULT {
var paintStruct win32.PAINTSTRUCT
log.Debug("window message recieved: ", msg)
defer log.Debug("window message processed: ", msg)

switch msg {
case win32.WM_PAINT:
Expand All @@ -124,27 +127,22 @@ func (r *APMTracker) windowProc(hwnd win32.HWND, msg uint32, wparam win32.WPARAM
win32.DT_RIGHT|win32.DT_NOCLIP|win32.DT_SINGLELINE|win32.DT_VCENTER,
)
win32.EndPaint(hwnd, &paintStruct)

return 0
case win32.WM_MOUSEMOVE, win32.WM_NCHITTEST, win32.WM_NCMOUSEMOVE, win32.WM_GETICON, win32.WM_LBUTTONDOWN, win32.WM_LBUTTONUP:
ret := win32.DefWindowProc(hwnd, msg, wparam, lparam)
return ret
case win32.WM_SETCURSOR:
ret := win32.DefWindowProc(hwnd, msg, wparam, lparam)
return ret
case refreshSignal:
// case win32.WM_MOUSEMOVE, win32.WM_NCHITTEST, win32.WM_NCMOUSEMOVE, win32.WM_GETICON, win32.WM_LBUTTONDOWN, win32.WM_LBUTTONUP:
// case win32.WM_SETCURSOR:
case win32.WM_TIMER:
var rect win32.RECT
win32.GetClientRect(hwnd, &rect)
win32.InvalidateRect(hwnd, &rect)
return 0
ok := win32.GetClientRect(hwnd, &rect)
log.Debug("getting rect status: ", ok)
invalidateOK := win32.InvalidateRect(hwnd, &rect)
log.Debug("getting invalid status: ", invalidateOK)
case win32.WM_CLOSE:
win32.DestroyWindow(hwnd)
case win32.WM_DESTROY:
win32.PostQuitMessage(0)
default:
ret := win32.DefWindowProc(hwnd, msg, wparam, lparam)
return ret
return win32.DefWindowProc(hwnd, msg, wparam, lparam)
}

return 0
}

Expand All @@ -160,6 +158,8 @@ const banner = `
`

func main() {
// log.SetLevel(log.DebugLevel)

fmt.Printf(banner, "v0.0.1")
// setup apm tracker
tracker := newAPMTracker()
Expand Down Expand Up @@ -220,19 +220,11 @@ func main() {
win32.SWP_NOACTIVATE|win32.SWP_NOMOVE|win32.SWP_NOSIZE|win32.SWP_SHOWWINDOW,
)

// refresh loop
done := make(chan int)
ticker := time.NewTicker(200 * time.Millisecond)
go func() {
for {
select {
case <-done:
return
case <-ticker.C:
win32.SendMessage(hwnd, refreshSignal, 0, 0)
}
}
}()
win32.ShowWindow(hwnd, 1)
win32.UpdateWindow(hwnd)

const timerID = 500
win32.SetTimer(hwnd, timerID, timerID, 0)

// pull messages
var msg win32.MSG
Expand Down

0 comments on commit 69477df

Please sign in to comment.